/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <stdio.h>
#include <fcntl.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <limits.h>
#include <libintl.h>
#include <locale.h>
#include <libproc.h>
#include <libscf.h>
#include <libscf_priv.h>
#include <assert.h>
#define COREADM_INST_FMRI \
static char *command;
static int alloptions;
static char *glob_pattern;
static char *init_pattern;
static char *proc_pattern;
static int report_settings(void);
static int do_processes(int, char **);
static int do_update(void);
static int do_legacy(void);
{ NULL }
};
static void
usage(void)
{
"usage:\n"));
" %s [ -g pattern ] [ -i pattern ] [ -G content ] [ -I content ]\n"),
command);
" [ -e {global | process | global-setid | proc-setid | log} ]\n"));
" [ -d {global | process | global-setid | proc-setid | log} ]\n"));
" %s [ -p pattern ] [ -P content ] [ pid ... ]\n"), command);
}
static int
perm(void)
{
"exercise the -[GIgied] options\n"), command);
return (E_USAGE);
}
static int
{
return (0);
return (1);
}
int
{
int flag;
int opt;
int modify;
int update = 0;
int legacy_update = 0;
int error = 0;
int npids;
char **pidlist;
(void) textdomain(TEXT_DOMAIN);
/* command name (e.g., "coreadm") */
command++;
else
switch (opt) {
case 'g':
break;
case 'i':
break;
case 'p':
break;
case 'G':
break;
case 'I':
break;
case 'P':
break;
case 'e':
case 'd':
else {
flag = 0;
error = 1;
}
if (opt == 'e')
else
alloptions |= flag;
break;
case 'U':
update = 1;
break;
case 'u':
legacy_update = 1;
break;
case '?':
default:
error = 1;
break;
}
}
if (error)
usage();
/*
* If 'modify' is true, we must modify the system settings
* and update the configuration file with the new parameters.
*/
alloptions != 0;
usage();
}
if (modify &&
"%s: -[GIgied] and -[Pp] options are mutually exclusive\n"),
command);
usage();
}
"%s: -[GIgied] options cannot have a process-id list\n"),
command);
usage();
}
npids == 0) {
npids = 1;
pidlist = &curpid_ptr;
}
if (legacy_update)
return (do_legacy());
if (update)
return (do_update());
if (modify)
if (npids != 0)
return (report_settings());
}
static int
report_settings(void)
{
perror("core_get_options()");
return (E_ERROR);
}
perror("core_get_global_path()");
return (E_ERROR);
}
perror("core_get_default_path()");
return (E_ERROR);
}
if (core_get_global_content(&glob_content) != 0) {
perror("core_get_global_content()");
return (E_ERROR);
}
if (core_get_default_content(&init_content) != 0) {
perror("core_get_default_content()");
return (E_ERROR);
}
gpattern);
sizeof (content_str));
ipattern);
sizeof (content_str));
return (E_SUCCESS);
}
static int
{
char *next;
while (npids-- > 0) {
gettext("%s: invalid process-id\n"),
*pidlist);
} else if (core_get_process_path(process_path,
sizeof (process_path), pid) != 0 ||
} else {
sizeof (content_str));
}
pidlist++;
}
} else {
while (npids-- > 0) {
if (*next != '\0') {
gettext("%s: invalid process-id\n"),
*pidlist);
} else {
if (proc_pattern != NULL &&
}
if (proc_content != CC_CONTENT_INVALID &&
&proc_content, pid) != 0) {
}
}
pidlist++;
}
}
return (rc);
}
static void
{
}
static boolean_t
{
return (result);
}
/*
* The user has specified the -g, -G, -i, -I, -d, or -e options to
* modify the given configuration parameter. Perform the modification
* in the smf repository and then perform a smf_refresh_instance which
* will cause a coreadm -u to occur which will transfer ALL coreadm
* configuration information from the repository to the kernel.
*/
static int
{
int count = 0;
return (E_ERROR);
}
if (glob_pattern != NULL)
if (glob_content != CC_CONTENT_INVALID) {
sizeof (gcontentstr));
}
if (init_pattern != NULL)
if (init_content != CC_CONTENT_INVALID) {
sizeof (icontentstr));
}
&prop) == SCF_FAILED) {
"%s: Unable to write property '%s': %s"), command,
} else {
"%s: Unable to write configuration: %s\n"),
}
return (E_ERROR);
}
if (smf_refresh_instance(COREADM_INST_FMRI) != 0) {
gettext("%s: Unable to refresh %s: %s\n"
"Configuration stored but not made active.\n"),
return (E_ERROR);
}
return (E_SUCCESS);
}
static const char *
write_kernel(void)
{
return ("core_set_global_path()");
if (core_set_global_content(&glob_content) != 0)
return ("core_set_global_content()");
return ("core_set_default_path()");
if (core_set_default_content(&init_content) != 0)
return ("core_set_init_content()");
if (core_set_options((int)options) != 0)
return ("core_set_options()");
return (NULL);
}
/*
* BUFSIZE must be large enough to contain the longest path plus some more.
*/
static int
{
return (1);
return (0);
"\"%s\", line %d: warning: value must be yes or no: %s=%s\n"),
return (0);
}
static int
read_legacy(void)
{
int line;
int n, len;
/* defaults */
gpattern[0] = '\0';
return (0);
/*
* Skip comment lines and empty lines.
*/
continue;
/*
* Look for "name=value", with optional whitespace on either
* side, terminated by a newline, and consuming the whole line.
*/
/* LINTED - unbounded string specifier */
if (n == 1)
value[0] = '\0';
continue;
}
continue;
}
continue;
}
continue;
}
continue;
}
else
options &= ~CC_PROCESS_PATH;
continue;
}
continue;
}
continue;
}
options |= CC_GLOBAL_LOG;
continue;
}
"\"%s\", line %d: warning: invalid token: %s\n"),
} else {
gettext("\"%s\", line %d: syntax error\n"),
PATH_CONFIG, line);
}
}
return (1);
}
/*
* Loads and applies the coreadm configuration stored in the default
* coreadm instance. As this option is (only) used from within an SMF
* service method, this function must return an SMF_EXIT_* exit status
* to its caller.
*/
static int
do_update(void)
{
int count = 0;
const char *errstr;
if (read_legacy()) {
goto error;
"%s: failed to import legacy configuration.\n"),
command);
return (SMF_EXIT_ERR_FATAL);
}
return (SMF_EXIT_OK);
}
"%s: configuration property '%s' not found.\n"),
} else {
"%s: unable to read configuration: %s\n"),
}
return (SMF_EXIT_ERR_FATAL);
}
errstr = write_kernel();
return (SMF_EXIT_OK);
(void) perm();
return (SMF_EXIT_ERR_PERM);
}
return (SMF_EXIT_ERR_FATAL);
}
static int do_legacy()
{
const char *errstr;
return (perm());
return (E_ERROR);
}
return (E_SUCCESS);
}