/*
* 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
*/
/*
*/
/*
* svccfg(1) interpreter and command execution engine.
*/
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <libintl.h>
#include <libtecla.h>
#include <md5.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "manifest_find.h"
#include "manifest_hash.h"
#include "svccfg.h"
/*
* Replacement lex(1) character retrieval routines.
*/
int
{
if (E->sc_cmd_file != NULL)
return (getc(E->sc_cmd_file));
if (E->sc_cmd_flags & SC_CMD_EOF)
return (EOF);
if (E->sc_cmd_bufoff < E->sc_cmd_bufsz)
return (*(E->sc_cmd_buf + E->sc_cmd_bufoff++));
if (!(E->sc_cmd_flags & SC_CMD_IACTIVE)) {
E->sc_cmd_flags |= SC_CMD_EOF;
return (EOF);
} else {
#ifdef NATIVE_BUILD
return (EOF);
#else
extern int parens;
if (parens <= 0) {
E->sc_cmd_flags |= SC_CMD_EOF;
return (EOF);
}
for (;;) {
if (E->sc_cmd_buf != NULL)
break;
switch (gl_return_status(E->sc_gl)) {
case GLR_SIGNAL:
gl_abandon_line(E->sc_gl);
continue;
case GLR_EOF:
E->sc_cmd_flags |= SC_CMD_EOF;
return (EOF);
case GLR_ERROR:
/* NOTREACHED */
default:
#ifndef NDEBUG
"returned unexpected value %d.\n", __FILE__,
#endif
abort();
}
}
E->sc_cmd_bufoff = 1;
return (E->sc_cmd_buf[0]);
#endif /* NATIVE_BUILD */
}
}
int
{
if (E->sc_cmd_file != NULL)
return (ungetc(c, E->sc_cmd_file));
if (E->sc_cmd_buf != NULL)
*(E->sc_cmd_buf + --E->sc_cmd_bufoff) = c;
return (c);
}
/*ARGSUSED*/
void
{
/* our lexer shouldn't need this state */
exit(11);
}
int
{
est->sc_cmd_bufoff = 0;
(void) yyparse();
return (0);
}
#ifndef NATIVE_BUILD
/* ARGSUSED */
static
{
const char *ext;
return (0);
}
static
{
return (0);
cfc = new_CplFileConf();
return (1);
}
(void) del_CplFileConf(cfc);
return (ret);
}
static struct cmd_info {
const char *name;
} cmds[] = {
{ NULL }
};
int
{
const char *bol;
continue;
if (err != 0)
return (err);
}
}
return (0);
}
/*
* Suggest completions. We must first determine if the cursor is in command
* position or in argument position. If the former, complete_command() finds
* matching commands. If the latter, we tail-call the command-specific
* argument-completion routine in the cmds table.
*/
/* ARGSUSED */
static
{
continue;
continue;
break;
word_end));
}
return (0);
}
#endif /* NATIVE_BUILD */
int
{
#ifdef NATIVE_BUILD
uu_die("native build does not support interactive mode.");
#else
char *selfmri;
int r;
extern int parens;
/* The longest string is "[snapname]fmri[:instname]> ". */
assert(r == 0);
for (;;) {
case GLR_SIGNAL:
continue;
case GLR_EOF:
break;
case GLR_ERROR:
/* NOTREACHED */
default:
#ifndef NDEBUG
"returned unexpected value %d.\n", __FILE__,
#endif
abort();
}
break;
}
parens = 0;
est->sc_cmd_bufoff = 0;
(void) yyparse();
}
#endif /* NATIVE_BUILD */
return (0);
}
int
{
int ret;
/* first, copy the stuff set up in engine_init */
/* set up the new guy */
if (dont_exit)
} else {
errno = 0;
if (errno == 0)
else
ret = -1;
goto fail;
}
do {
if (ret != 0) {
ret = -1;
goto fail;
}
ret = -1;
goto fail;
}
}
(void) yyparse();
ret = 0;
fail:
lscf_cleanup(); /* clean up any new repository */
return (ret);
}
/*
* Initialize svccfg state. We recognize four environment variables:
*
* SVCCFG_REPOSITORY Create a private instance of svc.configd(1M) to answer
* requests for the specified repository file.
* SVCCFG_DOOR_PATH Directory for door creation.
*
* SVCCFG_DOOR Rendezvous via an alternative repository door.
*
* SVCCFG_CONFIGD_PATH Resolvable path to alternative svc.configd(1M) binary.
*/
void
{
const char *cp;
"SVCCFG_REPOSITORY specified\n"));
} else {
}
}
}
static int
{
bundle_t *b;
const char *file;
/* Load the manifest */
b = internal_bundle_new();
return (-1);
}
/* Validate */
char *prefix;
} else {
prefix = "";
}
}
return (-1);
}
}
/* Import */
}
return (-1);
}
char *errstr;
if (errstr)
else
"mhash_store_entry() for %s\n"),
}
}
return (0);
}
/*
* Return values:
* 1 No manifests need to be imported.
* 0 Success
* -1 Error
* -2 Syntax error
*/
int
{
int argc, i, o;
int dont_exit;
int failed_manifests;
int total_manifests;
char *file;
int dirarg = 0;
int isdir;
char **paths;
int progress_count;
int back_count;
int count;
int fm_flags;
if (argc < 1)
return (-2);
opterr = 0;
optind = 0; /* Remember, no argv[0]. */
for (;;) {
if (o == -1)
break;
switch (o) {
case 'n':
flags |= SCI_NOREFRESH;
break;
case 'p':
break;
case 'V':
break;
case '?':
return (-2);
default:
bad_error("getopt", o);
}
}
if (argc < 1) {
return (-2);
}
/* Open device for progress messages */
if (progress_file != NULL) {
} else {
if (progress_out == NULL) {
"progress reporting. %s\n"),
goto out;
}
}
}
/* If we're in interactive mode, force strict validation. */
/* Determine which manifests must be imported. */
total_manifests = 0;
for (i = 0; i < argc; i++) {
/* Determine if argument is a directory or file. */
goto out;
}
dirarg = 1;
isdir = 1;
isdir = 0;
} else {
"file\n"), file);
goto out;
}
/* Get list of manifests that we should import for this path. */
fm_flags)) < 0) {
if (isdir) {
file);
} else {
file);
}
goto out;
}
total_manifests += count;
manifest_sets[i] = manifests;
}
if (total_manifests == 0) {
/* No manifests to process. */
if (g_verbose) {
}
rc = 1;
goto out;
}
/*
* If we're processing more than one file, we don't want to exit if
* we encounter an error. We should go ahead and process all of
* the manifests.
*/
if (total_manifests > 1)
if (progress_out != NULL)
(void) fprintf(progress_out,
"Loading smf(5) service descriptions: ");
failed_manifests = 0;
progress_count = 0;
for (i = 0; i < argc; i++) {
manifests = manifest_sets[i];
continue;
if (progress_out != NULL) {
while (back_count-- > 0) {
}
}
progress_out, flags) != 0) {
}
}
}
if (progress_out != NULL)
if (dirarg && total_manifests > 0) {
char *msg;
msg = "Loaded %d smf(5) service descriptions\n";
if (failed_manifests) {
msg = "%d smf(5) service descriptions failed to load\n";
}
}
if (failed_manifests > 0)
goto out;
if (g_verbose)
rc = 0;
out:
(void) fclose(progress_out);
if (manifest_sets != NULL) {
for (i = 0; i < argc; i++) {
}
}
return (rc);
}
/*
* Walk each service and get its manifest file.
*
* If the file exists check instance support, and cleanup any
* stale instances.
*
* that are no longer supported by files.
*/
int
{
int dont_exit;
int r = -1;
if (flags == 1) {
}
uu_warn) == SCF_SUCCESS)
r = 0;
if (dont_exit == 0)
(void) lscf_hash_cleanup();
return (r);
}
static int
{
bundle_t *b = internal_bundle_new();
return (-1);
}
if (!apply_changes) { /* we don't want to apply, just test */
return (0);
}
return (-1);
}
char *errstr;
}
}
return (0);
}
int
{
int rc = 0;
int isdir;
int dont_exit;
int profile_count;
int fm_flags;
/* Determine which profile(s) must be applied. */
profile_count = 0;
/* Determine if argument is a directory or file. */
rc = -1;
goto out;
}
isdir = 1;
isdir = 0;
} else {
"file\n"), file);
rc = -1;
goto out;
}
/* Get list of profiles to be applied. */
fm_flags)) < 0) {
if (isdir) {
} else {
}
rc = -1;
goto out;
}
if (profile_count == 0) {
/* No profiles to process. */
if (g_verbose) {
}
goto out;
}
/*
* We don't want to exit if we encounter an error. We should go ahead
* and process all of the profiles.
*/
if (g_verbose) {
}
} else {
rc = -1;
}
}
if (dont_exit == 0)
/* exit(1) appropriately if any profile failed to be applied. */
if ((rc == -1) &&
exit(1);
}
out:
return (rc);
}
int
{
bundle_t *b;
b = internal_bundle_new();
return (-1);
}
return (-1);
}
return (0);
}
int
{
/* Display current options. */
if (!g_verbose)
(void) puts("verbose");
return (0);
}
/* Use getopt? */
char *op;
switch (*op) {
case 'v':
g_verbose = 1;
break;
case 'V':
g_verbose = 0;
break;
default:
*op);
}
}
} else {
}
}
return (0);
}
void
{
int i;
if (com == 0) {
"Manifest commands: inventory validate import export "
"archive\n"
"Profile commands: apply extract\n"
"Entity commands: list select unselect add delete "
"describe\n"
"Snapshot commands: listsnap selectsnap revert\n"
"Instance commands: refresh\n"
"Property group commands: listpg addpg delpg\n"
"Property commands: listprop setprop delprop editprop\n"
"Property value commands: addpropvalue delpropvalue "
"setenv unsetenv\n"
"Notification parameters: "
"listnotify setnotify delnotify\n"));
return;
}
return;
}
}
}