void audit_ftpd_logout(void) { int rd; /* audit record descriptor */ uid_t euid; gid_t egid; uid_t uid; gid_t gid; pid_t pid; struct auditinfo_addr info; if (cannot_audit(0)) { return; } (void) priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_AUDIT, NULL); /* see if terminal id already set */ if (getaudit_addr(&info, sizeof (info)) < 0) { perror("getaudit"); } /* determine if we're preselected */ if (au_preselect(AUE_ftpd_logout, &info.ai_mask, AU_PRS_SUCCESS, AU_PRS_USECACHE) == 0) { (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_PROC_AUDIT, NULL); return; } euid = geteuid(); egid = getegid(); uid = getuid(); gid = getgid(); pid = getpid(); rd = au_open(); /* add subject token */ (void) au_write(rd, au_to_subject_ex(info.ai_auid, euid, egid, uid, gid, pid, pid, &info.ai_termid)); if (is_system_labeled()) (void) au_write(rd, au_to_mylabel()); /* add return token */ errno = 0; #ifdef _LP64 (void) au_write(rd, au_to_return64(0, (int64_t)0)); #else (void) au_write(rd, au_to_return32(0, (int32_t)0)); #endif /* write audit record */ if (au_close(rd, 1, AUE_ftpd_logout) < 0) { (void) au_close(rd, 0, 0); } (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_PROC_AUDIT, NULL); }
/* * To successfully handle some of link/root requests, some * file system operations need to be performed. These operations * should take place on behalf of the connected user (typically * Administrator) and to do so we need to have an infrastructure * in place so that smbd can act as a client and sends request to * the kernel. Right now, we lack this infrastructure, so we make * a compromise by temporarily enabling some privileges for smbd * to be able to fulfill various link/root requests. */ void dfs_setpriv(priv_op_t op) { (void) priv_set(op, PRIV_EFFECTIVE, PRIV_FILE_DAC_READ, PRIV_FILE_DAC_WRITE, PRIV_FILE_DAC_EXECUTE, PRIV_FILE_DAC_SEARCH, NULL); }
const char * get_ldap_secret() { FILE *f; size_t len; /* We require DAC_READ to open the secret file. */ if (priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_FILE_DAC_READ, NULL) == -1) { perror("get_ldap_secret: priv failure\n"); return NULL; } if ((f = fopen(SECRET, "r")) == NULL) { perror("cannot open LDAP secret"); goto err; } if (priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_FILE_DAC_READ, NULL) == -1) { (void) fprintf(stderr, "get_ldap_secret: priv failure\n"); _exit(1); } if (fgets(ldap_secret, sizeof ldap_secret, f) == NULL) { perror("cannot read LDAP secret"); goto err; } (void) fclose(f); len = strlen(ldap_secret); if (len && ldap_secret[len - 1] == '\n') ldap_secret[len - 1] = '\0'; return ldap_secret; err: if (f) (void) fclose(f); return NULL; }
static void setup_privs() { priv_set_t *privset; if (seteuid(getuid()) == -1 || setegid(getgid()) == -1) die(gettext("seteuid()/setegid() failed")); /* * Add our privileges and remove unneeded 'basic' privileges from the * permitted set. */ if ((privset = priv_str_to_set("basic", ",", NULL)) == NULL) die(gettext("cannot setup privileges")); (void) priv_addset(privset, PRIV_SYS_ACCT); (void) priv_addset(privset, PRIV_FILE_DAC_WRITE); (void) priv_addset(privset, PRIV_SYS_DL_CONFIG); (void) priv_delset(privset, PRIV_FILE_LINK_ANY); (void) priv_delset(privset, PRIV_PROC_EXEC); (void) priv_delset(privset, PRIV_PROC_FORK); (void) priv_delset(privset, PRIV_PROC_INFO); (void) priv_delset(privset, PRIV_PROC_SESSION); priv_inverse(privset); if (setppriv(PRIV_OFF, PRIV_PERMITTED, privset) == -1) die(gettext("cannot setup privileges")); priv_freeset(privset); /* * Clear the Inheritable and Limit sets. */ if ((privset = priv_allocset()) == NULL) die(gettext("cannot setup privileges")); priv_emptyset(privset); if (setppriv(PRIV_SET, PRIV_INHERITABLE, privset) == -1 || setppriv(PRIV_SET, PRIV_LIMIT, privset) == -1) die(gettext("cannot setup privileges")); /* * Turn off the sys_acct, file_dac_write and dl_config privileges * until needed. */ (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_FILE_DAC_WRITE, PRIV_SYS_ACCT, PRIV_SYS_DL_CONFIG, NULL); }
static int daemonSetupPrivs(void) { chown("/var/run/libvirt", SYSTEM_UID, SYSTEM_UID); if (__init_daemon_priv(PU_RESETGROUPS | PU_CLEARLIMITSET, SYSTEM_UID, SYSTEM_UID, PRIV_XVM_CONTROL, NULL)) { VIR_ERROR(_("additional privileges are required")); return -1; } if (priv_set(PRIV_OFF, PRIV_ALLSETS, PRIV_FILE_LINK_ANY, PRIV_PROC_INFO, PRIV_PROC_SESSION, PRIV_PROC_EXEC, PRIV_PROC_FORK, NULL)) { VIR_ERROR(_("failed to set reduced privileges")); return -1; } return 0; }
static int rmvolmgr(int argc, char **argv) { const char *opts = "chnsv"; DBusError error; boolean_t daemonize; rmm_error_t rmm_error; int c; while ((c = getopt(argc, argv, opts)) != EOF) { switch (c) { case 'c': opt_c = B_TRUE; break; case 'n': opt_n = B_TRUE; break; case 's': opt_s = B_TRUE; break; case 'v': rmm_debug = 1; break; case '?': case 'h': usage(); return (0); default: usage(); return (1); } } if (opt_s) { if (geteuid() != 0) { (void) fprintf(stderr, gettext("system instance must have euid 0\n")); return (1); } get_smf_properties(); if (opt_c) { rmm_vold_actions_enabled = B_FALSE; } if (opt_n) { rmm_vold_mountpoints_enabled = B_FALSE; } /* * Drop unused privileges. Remain root for HAL interaction * and to create legacy symlinks. * * Need PRIV_FILE_DAC_WRITE to write to users' * /tmp/.removable/notify* files. */ if (__init_daemon_priv(PU_RESETGROUPS|PU_CLEARLIMITSET, 0, 0, rmm_vold_actions_enabled ? PRIV_FILE_DAC_WRITE : NULL, NULL) == -1) { (void) fprintf(stderr, gettext("failed to drop privileges")); return (1); } /* basic privileges we don't need */ (void) priv_set(PRIV_OFF, PRIV_PERMITTED, PRIV_PROC_EXEC, PRIV_PROC_INFO, PRIV_FILE_LINK_ANY, PRIV_PROC_SESSION, NULL); } else { if (opt_c) { rmm_vold_actions_enabled = B_FALSE; } if (opt_n) { rmm_vold_mountpoints_enabled = B_FALSE; } } daemonize = (getenv("RMVOLMGR_NODAEMON") == NULL); if (daemonize && daemon(0, 0) < 0) { dprintf("daemonizing failed: %s", strerror(errno)); return (1); } if (opt_s) { __fini_daemon_priv(PRIV_PROC_FORK, NULL); } /* * signal mainloop integration using pipes */ if (pipe(sigexit_pipe) != 0) { dprintf("pipe failed %s\n", strerror(errno)); return (1); } sigexit_ioch = g_io_channel_unix_new(sigexit_pipe[0]); if (sigexit_ioch == NULL) { dprintf("g_io_channel_unix_new failed\n"); return (1); } g_io_add_watch(sigexit_ioch, G_IO_IN, sigexit_ioch_func, NULL); signal(SIGTERM, sigexit); signal(SIGINT, sigexit); signal(SIGHUP, SIG_IGN); signal(SIGUSR1, SIG_IGN); signal(SIGUSR2, SIG_IGN); if ((hal_ctx = rmm_hal_init(rmm_device_added, rmm_device_removed, rmm_property_modified, rmm_device_condition, &error, &rmm_error)) == NULL) { dbus_error_free(&error); return (1); } /* user instance should claim devices */ if (!opt_s) { if (!rmm_hal_claim_branch(hal_ctx, HAL_BRANCH_LOCAL)) { (void) fprintf(stderr, gettext("cannot claim branch\n")); return (1); } } rmm_mount_all(); if ((mainloop = g_main_loop_new(NULL, B_FALSE)) == NULL) { dprintf("Cannot create main loop\n"); return (1); } g_main_loop_run(mainloop); return (0); }
int main(int argc, char **argv) { int s; int c; (void) setlocale(LC_ALL, ""); #if !defined(TEXT_DOMAIN) #define TEXT_DOMAIN "SYS_TEST" #endif static const char daemon_dir[] = DAEMON_DIR; (void) textdomain(TEXT_DOMAIN); while ((c = getopt(argc, argv, ":V?d(debug)")) != -1) { switch ((char)c) { case '?': Usage(argv[0]); /* not reached */ break; case 'V': print_version(argv[0]); /* not reached */ break; case 'd': ilbd_enable_debug(); break; default: Usage(argv[0]); /* not reached */ break; } } /* * Whenever the daemon starts, it needs to start with a clean * slate in the kernel. We need sys_ip_config privilege for * this. */ ilbd_reset_kernel_state(); /* Increase the limit on the number of file descriptors. */ set_rlim(); /* * ilbd daemon starts off as root, just so it can create * /var/run/daemon if one does not exist. After that is done * the daemon switches to "daemon" uid. This is similar to what * rpcbind does. */ if (mkdir(daemon_dir, DAEMON_DIR_MODE) == 0 || errno == EEXIST) { (void) chmod(daemon_dir, DAEMON_DIR_MODE); (void) chown(daemon_dir, DAEMON_UID, DAEMON_GID); } else { perror("main: mkdir failed"); exit(errno); } /* * Now lets switch ilbd as uid = daemon, gid = daemon with a * trimmed down privilege set */ if (__init_daemon_priv(PU_RESETGROUPS | PU_LIMITPRIVS | PU_INHERITPRIVS, DAEMON_UID, DAEMON_GID, PRIV_PROC_OWNER, PRIV_PROC_AUDIT, PRIV_NET_ICMPACCESS, PRIV_SYS_IP_CONFIG, NULL) == -1) { (void) fprintf(stderr, "Insufficient privileges\n"); exit(EXIT_FAILURE); } /* * Opens a PF_UNIX socket to the client. No privilege needed * for this. */ s = ilbd_create_client_socket(); /* * Daemonify if ilbd is not running with -d option * Need proc_fork privilege for this */ if (!is_debugging_on()) { logdebug("daemonizing..."); if (daemon(0, 0) != 0) { logperror("daemon failed"); exit(EXIT_FAILURE); } } (void) priv_set(PRIV_OFF, PRIV_INHERITABLE, PRIV_PROC_OWNER, PRIV_PROC_AUDIT, NULL); /* if daemonified then set up syslog */ if (!is_debugging_on()) openlog("ilbd", LOG_PID, LOG_DAEMON); i_ilbd_setup_lists(); main_loop(s); /* * if we come here, then we experienced an error or a shutdown * indicator, so clean up after ourselves. */ logdebug("main(): terminating"); (void) remove(SOCKET_PATH); ilbd_reset_kernel_state(); return (0); }
int main(int argc, char *argv[]) { int c; /* options character */ int type = 0; /* type of accounting */ int modified = 0; /* have we modified any properties? */ acctconf_t ac; /* current configuration */ char *typestr = NULL; /* type of accounting argument string */ char *enabled = NULL; /* enabled resources string */ char *disabled = NULL; /* disabled resources string */ char *file = NULL; int Eflg = 0; int Dflg = 0; int rflg = 0; int sflg = 0; int xflg = 0; int optcnt = 0; int state; const char *fmri; /* FMRI for this instance */ int err = 0; setup_privs(); (void) setlocale(LC_ALL, ""); (void) textdomain(TEXT_DOMAIN); (void) setpname(argv[0]); for (; optind < argc; optind++) { while ((c = getopt(argc, argv, OPTS)) != (int)EOF) { switch (c) { case 'd': disabled = optarg; break; case 'e': enabled = optarg; break; case 'D': Dflg = 1; optcnt++; break; case 'E': Eflg = 1; optcnt++; break; case 'f': file = optarg; optcnt++; break; case 'r': rflg = 1; optcnt++; break; case 's': sflg = 1; optcnt++; break; case 'x': xflg = 1; optcnt++; break; case '?': default: usage(); } } /* * Permanently give up euid 0, egid 0 and privileges we * don't need for the specified options. */ if (!(file || sflg)) { if (setreuid(getuid(), getuid()) == -1 || setregid(getgid(), getgid()) == -1) die(gettext("setreuid()/setregid() failed")); (void) priv_set(PRIV_OFF, PRIV_PERMITTED, PRIV_FILE_DAC_WRITE, NULL); } if (!(disabled || enabled || Dflg || Eflg || file || sflg || xflg)) (void) priv_set(PRIV_OFF, PRIV_PERMITTED, PRIV_SYS_ACCT, PRIV_SYS_DL_CONFIG, NULL); if (optind < argc) { if (typestr != NULL) { warn(gettext("illegal argument -- %s\n"), argv[optind]); usage(); } else { typestr = argv[optind]; } } } if (typestr != NULL) { if (strcmp(typestr, "process") == 0 || strcmp(typestr, "proc") == 0) type |= AC_PROC; else if (strcmp(typestr, "task") == 0) type |= AC_TASK; else if (strcmp(typestr, "flow") == 0) type |= AC_FLOW; else if (strcmp(typestr, "net") == 0) type |= AC_NET; else { warn(gettext("unknown accounting type -- %s\n"), typestr); usage(); } } else type = AC_PROC | AC_TASK | AC_FLOW | AC_NET; /* * Drop the DL config privilege if we are not working with * net. */ if ((type & AC_NET) == 0) { (void) priv_set(PRIV_OFF, PRIV_PERMITTED, PRIV_SYS_DL_CONFIG, NULL); } /* * check for invalid options */ if (optcnt > 1) usage(); /* * XXX For AC_NET, enabled/disabled should only be "basic" or * "extended" - need to check it here. */ if ((enabled || disabled) && (rflg || Dflg || sflg || xflg || Eflg)) usage(); if ((file || xflg || Dflg || Eflg || enabled || disabled) && !typestr) { warn(gettext("accounting type must be specified\n")); usage(); } if (rflg) { printgroups(type); return (E_SUCCESS); } /* * If no arguments have been passed then just print out the current * state and exit. */ if (!enabled && !disabled && !file && !Eflg && !rflg && !Dflg && !sflg && !xflg) { aconf_print(stdout, type); return (E_SUCCESS); } /* Open the libdladm handle */ if (dladm_open(&dld_handle) != DLADM_STATUS_OK) die(gettext("failed to open dladm handle\n")); /* * smf(5) start method. The FMRI to operate on is retrieved from the * SMF_FMRI environment variable that the restarter provides. */ if (sflg) { if ((fmri = getenv("SMF_FMRI")) != NULL) { int ret = aconf_setup(fmri); dladm_close(dld_handle); return (ret); } die(gettext("-s option should only be invoked by smf(5)\n")); } assert(type == AC_PROC || type == AC_TASK || type == AC_FLOW || type == AC_NET); if ((type == AC_FLOW || type == AC_NET) && getzoneid() != GLOBAL_ZONEID) die(gettext("%s accounting cannot be configured in " "non-global zones\n"), ac_type_name(type)); fmri = aconf_type2fmri(type); if (aconf_scf_init(fmri) == -1) die(gettext("cannot connect to repository for %s\n"), fmri); /* * Since the sys_acct the privilege allows use of acctctl() regardless * of the accounting type, we check the smf(5) authorizations granted * to the user to determine whether the user is allowed to change the * configuration for this particular accounting type. */ if (!aconf_have_smf_auths()) die(gettext("insufficient authorization to change %s extended " "accounting configuration\n"), ac_type_name(type)); if (xflg) { /* * Turn off the specified accounting and close its file */ /* * Stop net logging before turning it off so that the last * set of logs can be written. */ if (type & AC_NET) { (void) priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_SYS_DL_CONFIG, NULL); err = dladm_stop_usagelog(dld_handle, DLADM_LOGTYPE_FLOW); (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_SYS_DL_CONFIG, NULL); if (err != DLADM_STATUS_OK) { die(gettext("failed to stop logging network " "information, error %d\n"), errno); } } state = AC_OFF; (void) priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_SYS_ACCT, NULL); if (acctctl(type | AC_STATE_SET, &state, sizeof (int)) == -1) die(gettext("cannot disable %s accounting"), ac_type_name(type)); if (acctctl(type | AC_FILE_SET, NULL, 0) == -1) die(gettext("cannot close %s accounting file\n"), ac_type_name(type)); (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_SYS_ACCT, NULL); if (aconf_set_bool(AC_PROP_STATE, B_FALSE) == -1) die(gettext("cannot update %s property\n"), AC_PROP_STATE); if (aconf_set_string(AC_PROP_FILE, AC_STR_NONE) == -1) die(gettext("cannot update %s property\n"), AC_PROP_FILE); modified++; } if (enabled || disabled) { char *tracked, *untracked; ac_res_t *buf; /* * Enable/disable resources */ if ((buf = malloc(AC_BUFSIZE)) == NULL) die(gettext("not enough memory\n")); (void) memset(buf, 0, AC_BUFSIZE); if (acctctl(type | AC_RES_GET, buf, AC_BUFSIZE) == -1) { free(buf); die(gettext("cannot obtain list of resources\n")); } if (disabled) { /* * Stop net logging before turning it off so that the * last set of logs can be written. */ if (type & AC_NET) { (void) priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_SYS_DL_CONFIG, NULL); err = dladm_stop_usagelog(dld_handle, strcmp(disabled, "basic") == 0 ? DLADM_LOGTYPE_LINK : DLADM_LOGTYPE_FLOW); (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_SYS_DL_CONFIG, NULL); if (err != DLADM_STATUS_OK) { die(gettext("failed to stop logging " "network information, error %d\n"), errno); } } str2buf(buf, disabled, AC_OFF, type); } else if (enabled) { str2buf(buf, enabled, AC_ON, type); } (void) priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_SYS_ACCT, NULL); if (acctctl(type | AC_RES_SET, buf, AC_BUFSIZE) == -1) { free(buf); die(gettext("cannot enable/disable %s accounting " "resources\n"), ac_type_name(type)); } (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_SYS_ACCT, NULL); tracked = buf2str(buf, AC_BUFSIZE, AC_ON, type); untracked = buf2str(buf, AC_BUFSIZE, AC_OFF, type); if (aconf_set_string(AC_PROP_TRACKED, tracked) == -1) die(gettext("cannot update %s property\n"), AC_PROP_TRACKED); if (aconf_set_string(AC_PROP_UNTRACKED, untracked) == -1) die(gettext("cannot update %s property\n"), AC_PROP_UNTRACKED); free(tracked); free(untracked); free(buf); modified++; } if (file) { /* * Open new accounting file */ (void) priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_SYS_ACCT, NULL); if (open_exacct_file(file, type) == -1) { dladm_close(dld_handle); exit(E_ERROR); } if (aconf_set_string(AC_PROP_FILE, file) == -1) die(gettext("cannot update %s property\n"), AC_PROP_FILE); state = AC_ON; if (acctctl(type | AC_STATE_SET, &state, sizeof (int)) == -1) die(gettext("cannot enable %s accounting"), ac_type_name(type)); (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_SYS_ACCT, NULL); if (aconf_set_bool(AC_PROP_STATE, B_TRUE) == -1) die(gettext("cannot update %s property\n"), AC_PROP_STATE); modified++; } /* * Let's get network logging started. We do this after turning on * accounting and opening the file so that we can start writing * immediately. */ if (enabled && (type & AC_NET)) { /* * Default logging interval for AC_NET is * ACCTADM_NET_LOG_INTERVAL. */ (void) priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_SYS_DL_CONFIG, NULL); err = dladm_start_usagelog(dld_handle, strcmp(enabled, "basic") == 0 ? DLADM_LOGTYPE_LINK : DLADM_LOGTYPE_FLOW, ACCTADM_NET_LOG_INTERVAL); (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_SYS_DL_CONFIG, NULL); if (err != DLADM_STATUS_OK) { die(gettext("failed to start logging " "network information, error %d\n"), errno); } } if (Dflg) { /* * Disable accounting */ /* * Stop net logging before turning it off so that the last * set of logs can be written. */ if (type & AC_NET) { (void) priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_SYS_DL_CONFIG, NULL); err = dladm_stop_usagelog(dld_handle, DLADM_LOGTYPE_FLOW); (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_SYS_DL_CONFIG, NULL); if (err != DLADM_STATUS_OK) { die(gettext("failed to stop logging " "network information, error %d\n"), errno); } } state = AC_OFF; (void) priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_SYS_ACCT, NULL); if (acctctl(type | AC_STATE_SET, &state, sizeof (int)) == -1) die(gettext("cannot disable %s accounting"), ac_type_name(type)); (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_SYS_ACCT, NULL); if (aconf_set_bool(AC_PROP_STATE, B_FALSE) == -1) die(gettext("cannot update %s property\n"), AC_PROP_STATE); modified++; } if (Eflg) { /* * Enable accounting */ /* * Let's get network logging started. */ if (type & AC_NET) { /* * Default logging interval for AC_NET is * ACCTADM_NET_LOG_INTERVAL. */ (void) priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_SYS_DL_CONFIG, NULL); err = dladm_start_usagelog(dld_handle, DLADM_LOGTYPE_FLOW, ACCTADM_NET_LOG_INTERVAL); (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_SYS_DL_CONFIG, NULL); if (err != DLADM_STATUS_OK) { die(gettext("failed to start logging " "network information, error %d\n"), errno); } } state = AC_ON; (void) priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_SYS_ACCT, NULL); if (acctctl(type | AC_STATE_SET, &state, sizeof (int)) == -1) die(gettext("cannot enable %s accounting"), ac_type_name(type)); (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_SYS_ACCT, NULL); if (aconf_set_bool(AC_PROP_STATE, B_TRUE) == -1) die(gettext("cannot update %s property\n"), AC_PROP_STATE); modified++; } (void) priv_set(PRIV_OFF, PRIV_PERMITTED, PRIV_SYS_ACCT, NULL); if (modified) { char *smf_state; if (aconf_save() == -1) die(gettext("cannot save %s accounting " "configuration\n"), ac_type_name(type)); /* * Enable or disable the instance depending on the effective * configuration. If the effective configuration results in * extended accounting being 'on', the instance is enabled so * the configuration is applied at the next boot. */ smf_state = smf_get_state(fmri); aconf_init(&ac, type); if (ac.state == AC_ON || strcmp(ac.file, AC_STR_NONE) != 0 || strcmp(ac.tracked, AC_STR_NONE) != 0) { if (strcmp(smf_state, SCF_STATE_STRING_ONLINE) != 0) if (smf_enable_instance(fmri, 0) == -1) die(gettext("cannot enable %s\n"), fmri); } else { if (strcmp(smf_state, SCF_STATE_STRING_ONLINE) == 0) if (smf_disable_instance(fmri, 0) == -1) die(gettext("cannot disable %s\n"), fmri); } free(smf_state); } aconf_scf_fini(); dladm_close(dld_handle); return (E_SUCCESS); }