17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 51f1b4534Scasper * Common Development and Distribution License (the "License"). 61f1b4534Scasper * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 213eae19d9Swesolows 227c478bd9Sstevel@tonic-gate /* 23adfc3118STruong Nguyen * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate /* 287c478bd9Sstevel@tonic-gate * svccfg(1) interpreter and command execution engine. 297c478bd9Sstevel@tonic-gate */ 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate #include <sys/mman.h> 327c478bd9Sstevel@tonic-gate #include <sys/stat.h> 337c478bd9Sstevel@tonic-gate #include <sys/types.h> 347c478bd9Sstevel@tonic-gate #include <assert.h> 357c478bd9Sstevel@tonic-gate #include <errno.h> 369444c26fSTom Whitten #include <fcntl.h> 377c478bd9Sstevel@tonic-gate #include <libintl.h> 387c478bd9Sstevel@tonic-gate #include <libtecla.h> 397c478bd9Sstevel@tonic-gate #include <md5.h> 407c478bd9Sstevel@tonic-gate #include <string.h> 417c478bd9Sstevel@tonic-gate #include <stdlib.h> 427c478bd9Sstevel@tonic-gate #include <unistd.h> 437c478bd9Sstevel@tonic-gate 449444c26fSTom Whitten #include "manifest_find.h" 457c478bd9Sstevel@tonic-gate #include "manifest_hash.h" 467c478bd9Sstevel@tonic-gate #include "svccfg.h" 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate #define MS_PER_US 1000 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate engine_state_t *est; 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate /* 537c478bd9Sstevel@tonic-gate * Replacement lex(1) character retrieval routines. 547c478bd9Sstevel@tonic-gate */ 557c478bd9Sstevel@tonic-gate int 567c478bd9Sstevel@tonic-gate engine_cmd_getc(engine_state_t *E) 577c478bd9Sstevel@tonic-gate { 587c478bd9Sstevel@tonic-gate if (E->sc_cmd_file != NULL) 597c478bd9Sstevel@tonic-gate return (getc(E->sc_cmd_file)); 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate if (E->sc_cmd_flags & SC_CMD_EOF) 627c478bd9Sstevel@tonic-gate return (EOF); 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate if (E->sc_cmd_bufoff < E->sc_cmd_bufsz) 657c478bd9Sstevel@tonic-gate return (*(E->sc_cmd_buf + E->sc_cmd_bufoff++)); 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate if (!(E->sc_cmd_flags & SC_CMD_IACTIVE)) { 687c478bd9Sstevel@tonic-gate E->sc_cmd_flags |= SC_CMD_EOF; 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate return (EOF); 717c478bd9Sstevel@tonic-gate } else { 727c478bd9Sstevel@tonic-gate #ifdef NATIVE_BUILD 737c478bd9Sstevel@tonic-gate return (EOF); 747c478bd9Sstevel@tonic-gate #else 757c478bd9Sstevel@tonic-gate extern int parens; 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate if (parens <= 0) { 787c478bd9Sstevel@tonic-gate E->sc_cmd_flags |= SC_CMD_EOF; 797c478bd9Sstevel@tonic-gate return (EOF); 807c478bd9Sstevel@tonic-gate } 817c478bd9Sstevel@tonic-gate 827c478bd9Sstevel@tonic-gate for (;;) { 837c478bd9Sstevel@tonic-gate E->sc_cmd_buf = gl_get_line(E->sc_gl, "> ", NULL, -1); 847c478bd9Sstevel@tonic-gate if (E->sc_cmd_buf != NULL) 857c478bd9Sstevel@tonic-gate break; 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate switch (gl_return_status(E->sc_gl)) { 887c478bd9Sstevel@tonic-gate case GLR_SIGNAL: 897c478bd9Sstevel@tonic-gate gl_abandon_line(E->sc_gl); 907c478bd9Sstevel@tonic-gate continue; 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate case GLR_EOF: 937c478bd9Sstevel@tonic-gate E->sc_cmd_flags |= SC_CMD_EOF; 947c478bd9Sstevel@tonic-gate return (EOF); 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate case GLR_ERROR: 977c478bd9Sstevel@tonic-gate uu_die(gettext("Error reading terminal: %s.\n"), 987c478bd9Sstevel@tonic-gate gl_error_message(E->sc_gl, NULL, 0)); 997c478bd9Sstevel@tonic-gate /* NOTREACHED */ 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate default: 1027c478bd9Sstevel@tonic-gate #ifndef NDEBUG 1037c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s:%d: gl_get_line() " 1047c478bd9Sstevel@tonic-gate "returned unexpected value %d.\n", __FILE__, 1057c478bd9Sstevel@tonic-gate __LINE__, gl_return_status(E->sc_gl)); 1067c478bd9Sstevel@tonic-gate #endif 1077c478bd9Sstevel@tonic-gate abort(); 1087c478bd9Sstevel@tonic-gate } 1097c478bd9Sstevel@tonic-gate } 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate E->sc_cmd_bufsz = strlen(E->sc_cmd_buf); 1127c478bd9Sstevel@tonic-gate E->sc_cmd_bufoff = 1; 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate return (E->sc_cmd_buf[0]); 1157c478bd9Sstevel@tonic-gate #endif /* NATIVE_BUILD */ 1167c478bd9Sstevel@tonic-gate } 1177c478bd9Sstevel@tonic-gate } 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate int 1207c478bd9Sstevel@tonic-gate engine_cmd_ungetc(engine_state_t *E, char c) 1217c478bd9Sstevel@tonic-gate { 1227c478bd9Sstevel@tonic-gate if (E->sc_cmd_file != NULL) 1237c478bd9Sstevel@tonic-gate return (ungetc(c, E->sc_cmd_file)); 1247c478bd9Sstevel@tonic-gate 1257c478bd9Sstevel@tonic-gate if (E->sc_cmd_buf != NULL) 1267c478bd9Sstevel@tonic-gate *(E->sc_cmd_buf + --E->sc_cmd_bufoff) = c; 1277c478bd9Sstevel@tonic-gate 1287c478bd9Sstevel@tonic-gate return (c); 1297c478bd9Sstevel@tonic-gate } 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1327c478bd9Sstevel@tonic-gate void 1337c478bd9Sstevel@tonic-gate engine_cmd_nputs(engine_state_t *E, char *c, size_t n) 1347c478bd9Sstevel@tonic-gate { 1357c478bd9Sstevel@tonic-gate /* our lexer shouldn't need this state */ 1367c478bd9Sstevel@tonic-gate exit(11); 1377c478bd9Sstevel@tonic-gate } 1387c478bd9Sstevel@tonic-gate 1397c478bd9Sstevel@tonic-gate int 1407c478bd9Sstevel@tonic-gate engine_exec(char *cmd) 1417c478bd9Sstevel@tonic-gate { 1427c478bd9Sstevel@tonic-gate est->sc_cmd_buf = cmd; 1437c478bd9Sstevel@tonic-gate est->sc_cmd_bufsz = strlen(cmd) + 1; 1447c478bd9Sstevel@tonic-gate est->sc_cmd_bufoff = 0; 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate (void) yyparse(); 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate return (0); 1497c478bd9Sstevel@tonic-gate } 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate #ifndef NATIVE_BUILD 1527c478bd9Sstevel@tonic-gate /* ARGSUSED */ 1537c478bd9Sstevel@tonic-gate static 1547c478bd9Sstevel@tonic-gate CPL_CHECK_FN(check_xml) 1557c478bd9Sstevel@tonic-gate { 1567c478bd9Sstevel@tonic-gate const char *ext; 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate if (strlen(pathname) < 4) 1597c478bd9Sstevel@tonic-gate return (0); 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate ext = pathname + strlen(pathname) - 4; 1627c478bd9Sstevel@tonic-gate 1637c478bd9Sstevel@tonic-gate return (strcmp(ext, ".xml") == 0 ? 1 : 0); 1647c478bd9Sstevel@tonic-gate } 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate static const char * const whitespace = " \t"; 1677c478bd9Sstevel@tonic-gate 1687c478bd9Sstevel@tonic-gate static 1697c478bd9Sstevel@tonic-gate CPL_MATCH_FN(complete_single_xml_file_arg) 1707c478bd9Sstevel@tonic-gate { 1717c478bd9Sstevel@tonic-gate const char *arg1 = data; 1727c478bd9Sstevel@tonic-gate int arg1end_i, ret; 1737c478bd9Sstevel@tonic-gate CplFileConf *cfc; 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate arg1end_i = arg1 + strcspn(arg1, whitespace) - line; 1767c478bd9Sstevel@tonic-gate if (arg1end_i < word_end) 1777c478bd9Sstevel@tonic-gate return (0); 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate cfc = new_CplFileConf(); 1807c478bd9Sstevel@tonic-gate if (cfc == NULL) { 1817c478bd9Sstevel@tonic-gate cpl_record_error(cpl, "Out of memory."); 1827c478bd9Sstevel@tonic-gate return (1); 1837c478bd9Sstevel@tonic-gate } 1847c478bd9Sstevel@tonic-gate 1857c478bd9Sstevel@tonic-gate cfc_set_check_fn(cfc, check_xml, NULL); 1867c478bd9Sstevel@tonic-gate 1877c478bd9Sstevel@tonic-gate ret = cpl_file_completions(cpl, cfc, line, word_end); 1887c478bd9Sstevel@tonic-gate 1897c478bd9Sstevel@tonic-gate (void) del_CplFileConf(cfc); 1907c478bd9Sstevel@tonic-gate return (ret); 1917c478bd9Sstevel@tonic-gate } 1927c478bd9Sstevel@tonic-gate 1937c478bd9Sstevel@tonic-gate static struct cmd_info { 1947c478bd9Sstevel@tonic-gate const char *name; 1957c478bd9Sstevel@tonic-gate uint32_t flags; 1967c478bd9Sstevel@tonic-gate CplMatchFn *complete_args_f; 1977c478bd9Sstevel@tonic-gate } cmds[] = { 1987c478bd9Sstevel@tonic-gate { "validate", CS_GLOBAL, complete_single_xml_file_arg }, 1997c478bd9Sstevel@tonic-gate { "import", CS_GLOBAL, complete_single_xml_file_arg }, 2009444c26fSTom Whitten { "cleanup", CS_GLOBAL, NULL}, 2017c478bd9Sstevel@tonic-gate { "export", CS_GLOBAL, NULL }, 2027c478bd9Sstevel@tonic-gate { "archive", CS_GLOBAL, NULL }, 2037c478bd9Sstevel@tonic-gate { "apply", CS_GLOBAL, complete_single_xml_file_arg }, 2047c478bd9Sstevel@tonic-gate { "extract", CS_GLOBAL, NULL }, 2057c478bd9Sstevel@tonic-gate { "repository", CS_GLOBAL, NULL }, 2067c478bd9Sstevel@tonic-gate { "inventory", CS_GLOBAL, complete_single_xml_file_arg }, 2077c478bd9Sstevel@tonic-gate { "set", CS_GLOBAL, NULL }, 2087c478bd9Sstevel@tonic-gate { "end", CS_GLOBAL, NULL }, 2097c478bd9Sstevel@tonic-gate { "exit", CS_GLOBAL, NULL }, 2107c478bd9Sstevel@tonic-gate { "quit", CS_GLOBAL, NULL }, 2117c478bd9Sstevel@tonic-gate { "help", CS_GLOBAL, NULL }, 2127c478bd9Sstevel@tonic-gate { "delete", CS_GLOBAL, NULL }, 2137c478bd9Sstevel@tonic-gate { "select", CS_GLOBAL, complete_select }, 2147c478bd9Sstevel@tonic-gate { "unselect", CS_SVC | CS_INST | CS_SNAP, NULL }, 2157c478bd9Sstevel@tonic-gate { "list", CS_SCOPE | CS_SVC | CS_SNAP, NULL }, 2167c478bd9Sstevel@tonic-gate { "add", CS_SCOPE | CS_SVC, NULL }, 2177c478bd9Sstevel@tonic-gate { "listpg", CS_SVC | CS_INST | CS_SNAP, NULL }, 2187c478bd9Sstevel@tonic-gate { "addpg", CS_SVC | CS_INST, NULL }, 2197c478bd9Sstevel@tonic-gate { "delpg", CS_SVC | CS_INST, NULL }, 22070cbfe41SPhilippe Jung { "delhash", CS_GLOBAL, complete_single_xml_file_arg }, 2217c478bd9Sstevel@tonic-gate { "listprop", CS_SVC | CS_INST | CS_SNAP, NULL }, 2227c478bd9Sstevel@tonic-gate { "setprop", CS_SVC | CS_INST, NULL }, 2237c478bd9Sstevel@tonic-gate { "delprop", CS_SVC | CS_INST, NULL }, 2247c478bd9Sstevel@tonic-gate { "editprop", CS_SVC | CS_INST, NULL }, 2251f6eb021SLiane Praza { "describe", CS_SVC | CS_INST | CS_SNAP, NULL }, 2267c478bd9Sstevel@tonic-gate { "listsnap", CS_INST | CS_SNAP, NULL }, 2277c478bd9Sstevel@tonic-gate { "selectsnap", CS_INST | CS_SNAP, NULL }, 2287c478bd9Sstevel@tonic-gate { "revert", CS_INST | CS_SNAP, NULL }, 229347a77f2Samaguire { "refresh", CS_INST, NULL }, 2307c478bd9Sstevel@tonic-gate { NULL } 2317c478bd9Sstevel@tonic-gate }; 2327c478bd9Sstevel@tonic-gate 2337c478bd9Sstevel@tonic-gate int 2347c478bd9Sstevel@tonic-gate add_cmd_matches(WordCompletion *cpl, const char *line, int word_end, 2357c478bd9Sstevel@tonic-gate uint32_t scope) 2367c478bd9Sstevel@tonic-gate { 2377c478bd9Sstevel@tonic-gate int word_start, err; 2387c478bd9Sstevel@tonic-gate size_t len; 2397c478bd9Sstevel@tonic-gate const char *bol; 2407c478bd9Sstevel@tonic-gate struct cmd_info *cip; 2417c478bd9Sstevel@tonic-gate 2427c478bd9Sstevel@tonic-gate word_start = strspn(line, whitespace); 2437c478bd9Sstevel@tonic-gate len = word_end - word_start; 2447c478bd9Sstevel@tonic-gate bol = line + word_end - len; 2457c478bd9Sstevel@tonic-gate 2467c478bd9Sstevel@tonic-gate for (cip = cmds; cip->name != NULL; ++cip) { 2477c478bd9Sstevel@tonic-gate if ((cip->flags & scope) == 0) 2487c478bd9Sstevel@tonic-gate continue; 2497c478bd9Sstevel@tonic-gate 2507c478bd9Sstevel@tonic-gate if (strncmp(cip->name, bol, len) == 0) { 2517c478bd9Sstevel@tonic-gate err = cpl_add_completion(cpl, line, word_start, 2527c478bd9Sstevel@tonic-gate word_end, cip->name + len, "", " "); 2537c478bd9Sstevel@tonic-gate if (err != 0) 2547c478bd9Sstevel@tonic-gate return (err); 2557c478bd9Sstevel@tonic-gate } 2567c478bd9Sstevel@tonic-gate } 2577c478bd9Sstevel@tonic-gate 2587c478bd9Sstevel@tonic-gate return (0); 2597c478bd9Sstevel@tonic-gate } 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate /* 2627c478bd9Sstevel@tonic-gate * Suggest completions. We must first determine if the cursor is in command 2637c478bd9Sstevel@tonic-gate * position or in argument position. If the former, complete_command() finds 2647c478bd9Sstevel@tonic-gate * matching commands. If the latter, we tail-call the command-specific 2657c478bd9Sstevel@tonic-gate * argument-completion routine in the cmds table. 2667c478bd9Sstevel@tonic-gate */ 2677c478bd9Sstevel@tonic-gate /* ARGSUSED */ 2687c478bd9Sstevel@tonic-gate static 2697c478bd9Sstevel@tonic-gate CPL_MATCH_FN(complete) 2707c478bd9Sstevel@tonic-gate { 2717c478bd9Sstevel@tonic-gate const char *arg0, *arg1; 2727c478bd9Sstevel@tonic-gate size_t arg0len; 2737c478bd9Sstevel@tonic-gate struct cmd_info *cip; 2747c478bd9Sstevel@tonic-gate 2757c478bd9Sstevel@tonic-gate arg0 = line + strspn(line, whitespace); 2767c478bd9Sstevel@tonic-gate arg0len = strcspn(arg0, whitespace); 2777c478bd9Sstevel@tonic-gate if ((arg0 + arg0len) - line >= word_end || 2787c478bd9Sstevel@tonic-gate (arg0[arg0len] != ' ' && arg0[arg0len] != '\t')) 2797c478bd9Sstevel@tonic-gate return (complete_command(cpl, (void *)arg0, line, word_end)); 2807c478bd9Sstevel@tonic-gate 2817c478bd9Sstevel@tonic-gate arg1 = arg0 + arg0len; 2827c478bd9Sstevel@tonic-gate arg1 += strspn(arg1, whitespace); 2837c478bd9Sstevel@tonic-gate 2847c478bd9Sstevel@tonic-gate for (cip = cmds; cip->name != NULL; ++cip) { 2857c478bd9Sstevel@tonic-gate if (strlen(cip->name) != arg0len) 2867c478bd9Sstevel@tonic-gate continue; 2877c478bd9Sstevel@tonic-gate 2887c478bd9Sstevel@tonic-gate if (strncmp(cip->name, arg0, arg0len) != 0) 2897c478bd9Sstevel@tonic-gate continue; 2907c478bd9Sstevel@tonic-gate 2917c478bd9Sstevel@tonic-gate if (cip->complete_args_f == NULL) 2927c478bd9Sstevel@tonic-gate break; 2937c478bd9Sstevel@tonic-gate 2947c478bd9Sstevel@tonic-gate return (cip->complete_args_f(cpl, (void *)arg1, line, 2957c478bd9Sstevel@tonic-gate word_end)); 2967c478bd9Sstevel@tonic-gate } 2977c478bd9Sstevel@tonic-gate 2987c478bd9Sstevel@tonic-gate return (0); 2997c478bd9Sstevel@tonic-gate } 3007c478bd9Sstevel@tonic-gate #endif /* NATIVE_BUILD */ 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate int 3037c478bd9Sstevel@tonic-gate engine_interp() 3047c478bd9Sstevel@tonic-gate { 3057c478bd9Sstevel@tonic-gate #ifdef NATIVE_BUILD 3067c478bd9Sstevel@tonic-gate uu_die("native build does not support interactive mode."); 3077c478bd9Sstevel@tonic-gate #else 3087c478bd9Sstevel@tonic-gate char *selfmri; 3097c478bd9Sstevel@tonic-gate size_t sfsz; 3107c478bd9Sstevel@tonic-gate int r; 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate extern int parens; 3137c478bd9Sstevel@tonic-gate 3147c478bd9Sstevel@tonic-gate (void) sigset(SIGINT, SIG_IGN); 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate est->sc_gl = new_GetLine(512, 8000); 3177c478bd9Sstevel@tonic-gate if (est->sc_gl == NULL) 3187c478bd9Sstevel@tonic-gate uu_die(gettext("Out of memory.\n")); 3197c478bd9Sstevel@tonic-gate 3207c478bd9Sstevel@tonic-gate /* The longest string is "[snapname]fmri[:instname]> ". */ 3217c478bd9Sstevel@tonic-gate sfsz = 1 + max_scf_name_len + 1 + max_scf_fmri_len + 2 + 3227c478bd9Sstevel@tonic-gate max_scf_name_len + 1 + 2 + 1; 3237c478bd9Sstevel@tonic-gate selfmri = safe_malloc(sfsz); 3247c478bd9Sstevel@tonic-gate 3257c478bd9Sstevel@tonic-gate r = gl_customize_completion(est->sc_gl, NULL, complete); 3267c478bd9Sstevel@tonic-gate assert(r == 0); 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate for (;;) { 3297c478bd9Sstevel@tonic-gate lscf_get_selection_str(selfmri, sfsz - 2); 3307c478bd9Sstevel@tonic-gate (void) strcat(selfmri, "> "); 3317c478bd9Sstevel@tonic-gate est->sc_cmd_buf = gl_get_line(est->sc_gl, selfmri, NULL, -1); 3327c478bd9Sstevel@tonic-gate 3337c478bd9Sstevel@tonic-gate if (est->sc_cmd_buf == NULL) { 3347c478bd9Sstevel@tonic-gate switch (gl_return_status(est->sc_gl)) { 3357c478bd9Sstevel@tonic-gate case GLR_SIGNAL: 3367c478bd9Sstevel@tonic-gate gl_abandon_line(est->sc_gl); 3377c478bd9Sstevel@tonic-gate continue; 3387c478bd9Sstevel@tonic-gate 3397c478bd9Sstevel@tonic-gate case GLR_EOF: 3407c478bd9Sstevel@tonic-gate break; 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate case GLR_ERROR: 3437c478bd9Sstevel@tonic-gate uu_die(gettext("Error reading terminal: %s.\n"), 3447c478bd9Sstevel@tonic-gate gl_error_message(est->sc_gl, NULL, 0)); 3457c478bd9Sstevel@tonic-gate /* NOTREACHED */ 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate default: 3487c478bd9Sstevel@tonic-gate #ifndef NDEBUG 3497c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s:%d: gl_get_line() " 3507c478bd9Sstevel@tonic-gate "returned unexpected value %d.\n", __FILE__, 3517c478bd9Sstevel@tonic-gate __LINE__, gl_return_status(est->sc_gl)); 3527c478bd9Sstevel@tonic-gate #endif 3537c478bd9Sstevel@tonic-gate abort(); 3547c478bd9Sstevel@tonic-gate } 3557c478bd9Sstevel@tonic-gate 3567c478bd9Sstevel@tonic-gate break; 3577c478bd9Sstevel@tonic-gate } 3587c478bd9Sstevel@tonic-gate 3597c478bd9Sstevel@tonic-gate parens = 0; 3607c478bd9Sstevel@tonic-gate est->sc_cmd_bufsz = strlen(est->sc_cmd_buf); 3617c478bd9Sstevel@tonic-gate est->sc_cmd_bufoff = 0; 3627c478bd9Sstevel@tonic-gate est->sc_cmd_flags = SC_CMD_IACTIVE; 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate (void) yyparse(); 3657c478bd9Sstevel@tonic-gate } 3667c478bd9Sstevel@tonic-gate 3677c478bd9Sstevel@tonic-gate free(selfmri); 3687c478bd9Sstevel@tonic-gate est->sc_gl = del_GetLine(est->sc_gl); /* returns NULL */ 3697c478bd9Sstevel@tonic-gate 3707c478bd9Sstevel@tonic-gate #endif /* NATIVE_BUILD */ 3717c478bd9Sstevel@tonic-gate return (0); 3727c478bd9Sstevel@tonic-gate } 3737c478bd9Sstevel@tonic-gate 3747c478bd9Sstevel@tonic-gate int 3757c478bd9Sstevel@tonic-gate engine_source(const char *name, boolean_t dont_exit) 3767c478bd9Sstevel@tonic-gate { 3777c478bd9Sstevel@tonic-gate engine_state_t *old = est; 3787c478bd9Sstevel@tonic-gate struct stat st; 3797c478bd9Sstevel@tonic-gate int ret; 3807c478bd9Sstevel@tonic-gate 3817c478bd9Sstevel@tonic-gate est = uu_zalloc(sizeof (engine_state_t)); 3827c478bd9Sstevel@tonic-gate 3837c478bd9Sstevel@tonic-gate /* first, copy the stuff set up in engine_init */ 3847c478bd9Sstevel@tonic-gate est->sc_repo_pid = old->sc_repo_pid; 3857c478bd9Sstevel@tonic-gate if (old->sc_repo_filename != NULL) 3867c478bd9Sstevel@tonic-gate est->sc_repo_filename = safe_strdup(old->sc_repo_filename); 3877c478bd9Sstevel@tonic-gate if (old->sc_repo_doordir != NULL) 3887c478bd9Sstevel@tonic-gate est->sc_repo_doordir = safe_strdup(old->sc_repo_doordir); 3897c478bd9Sstevel@tonic-gate if (old->sc_repo_doorname != NULL) 3907c478bd9Sstevel@tonic-gate est->sc_repo_doorname = safe_strdup(old->sc_repo_doorname); 3917c478bd9Sstevel@tonic-gate if (old->sc_repo_server != NULL) 3927c478bd9Sstevel@tonic-gate est->sc_repo_server = safe_strdup(old->sc_repo_server); 3937c478bd9Sstevel@tonic-gate 3947c478bd9Sstevel@tonic-gate /* set up the new guy */ 3957c478bd9Sstevel@tonic-gate est->sc_cmd_lineno = 1; 3967c478bd9Sstevel@tonic-gate 3977c478bd9Sstevel@tonic-gate if (dont_exit) 3987c478bd9Sstevel@tonic-gate est->sc_cmd_flags |= SC_CMD_DONT_EXIT; 3997c478bd9Sstevel@tonic-gate 4007c478bd9Sstevel@tonic-gate if (strcmp(name, "-") == 0) { 4017c478bd9Sstevel@tonic-gate est->sc_cmd_file = stdin; 4027c478bd9Sstevel@tonic-gate est->sc_cmd_filename = "<stdin>"; 4037c478bd9Sstevel@tonic-gate } else { 4047c478bd9Sstevel@tonic-gate errno = 0; 4057c478bd9Sstevel@tonic-gate est->sc_cmd_filename = name; 4067c478bd9Sstevel@tonic-gate est->sc_cmd_file = fopen(name, "r"); 4077c478bd9Sstevel@tonic-gate if (est->sc_cmd_file == NULL) { 4087c478bd9Sstevel@tonic-gate if (errno == 0) 4097c478bd9Sstevel@tonic-gate semerr(gettext("No free stdio streams.\n")); 4107c478bd9Sstevel@tonic-gate else 4117c478bd9Sstevel@tonic-gate semerr(gettext("Could not open %s"), name); 4127c478bd9Sstevel@tonic-gate 4137c478bd9Sstevel@tonic-gate ret = -1; 4147c478bd9Sstevel@tonic-gate goto fail; 4157c478bd9Sstevel@tonic-gate } 4167c478bd9Sstevel@tonic-gate 4173eae19d9Swesolows do { 4187c478bd9Sstevel@tonic-gate ret = fstat(fileno(est->sc_cmd_file), &st); 4193eae19d9Swesolows } while (ret != 0 && errno == EINTR); 4207c478bd9Sstevel@tonic-gate if (ret != 0) { 4217c478bd9Sstevel@tonic-gate (void) fclose(est->sc_cmd_file); 4227c478bd9Sstevel@tonic-gate est->sc_cmd_file = NULL; /* for semerr() */ 4237c478bd9Sstevel@tonic-gate 4247c478bd9Sstevel@tonic-gate semerr(gettext("Could not stat %s"), name); 4257c478bd9Sstevel@tonic-gate 4267c478bd9Sstevel@tonic-gate ret = -1; 4277c478bd9Sstevel@tonic-gate goto fail; 4287c478bd9Sstevel@tonic-gate } 4297c478bd9Sstevel@tonic-gate 4307c478bd9Sstevel@tonic-gate if (!S_ISREG(st.st_mode)) { 4317c478bd9Sstevel@tonic-gate (void) fclose(est->sc_cmd_file); 4327c478bd9Sstevel@tonic-gate est->sc_cmd_file = NULL; /* for semerr() */ 4337c478bd9Sstevel@tonic-gate 4347c478bd9Sstevel@tonic-gate semerr(gettext("%s is not a regular file.\n"), name); 4357c478bd9Sstevel@tonic-gate 4367c478bd9Sstevel@tonic-gate ret = -1; 4377c478bd9Sstevel@tonic-gate goto fail; 4387c478bd9Sstevel@tonic-gate } 4397c478bd9Sstevel@tonic-gate } 4407c478bd9Sstevel@tonic-gate 4417c478bd9Sstevel@tonic-gate (void) yyparse(); 4427c478bd9Sstevel@tonic-gate 4437c478bd9Sstevel@tonic-gate if (est->sc_cmd_file != stdin) 4447c478bd9Sstevel@tonic-gate (void) fclose(est->sc_cmd_file); 4457c478bd9Sstevel@tonic-gate 4467c478bd9Sstevel@tonic-gate ret = 0; 4477c478bd9Sstevel@tonic-gate 4487c478bd9Sstevel@tonic-gate fail: 4497c478bd9Sstevel@tonic-gate if (est->sc_repo_pid != old->sc_repo_pid) 4507c478bd9Sstevel@tonic-gate lscf_cleanup(); /* clean up any new repository */ 4517c478bd9Sstevel@tonic-gate 4527c478bd9Sstevel@tonic-gate if (est->sc_repo_filename != NULL) 4537c478bd9Sstevel@tonic-gate free((void *)est->sc_repo_filename); 4547c478bd9Sstevel@tonic-gate if (est->sc_repo_doordir != NULL) 4557c478bd9Sstevel@tonic-gate free((void *)est->sc_repo_doordir); 4567c478bd9Sstevel@tonic-gate if (est->sc_repo_doorname != NULL) 4577c478bd9Sstevel@tonic-gate free((void *)est->sc_repo_doorname); 4587c478bd9Sstevel@tonic-gate if (est->sc_repo_server != NULL) 4597c478bd9Sstevel@tonic-gate free((void *)est->sc_repo_server); 4607c478bd9Sstevel@tonic-gate free(est); 4617c478bd9Sstevel@tonic-gate 4627c478bd9Sstevel@tonic-gate est = old; 4637c478bd9Sstevel@tonic-gate 4647c478bd9Sstevel@tonic-gate return (ret); 4657c478bd9Sstevel@tonic-gate } 4667c478bd9Sstevel@tonic-gate 4677c478bd9Sstevel@tonic-gate /* 4687c478bd9Sstevel@tonic-gate * Initialize svccfg state. We recognize four environment variables: 4697c478bd9Sstevel@tonic-gate * 4707c478bd9Sstevel@tonic-gate * SVCCFG_REPOSITORY Create a private instance of svc.configd(1M) to answer 4717c478bd9Sstevel@tonic-gate * requests for the specified repository file. 4727c478bd9Sstevel@tonic-gate * SVCCFG_DOOR_PATH Directory for door creation. 4737c478bd9Sstevel@tonic-gate * 4747c478bd9Sstevel@tonic-gate * SVCCFG_DOOR Rendezvous via an alternative repository door. 4757c478bd9Sstevel@tonic-gate * 4767c478bd9Sstevel@tonic-gate * SVCCFG_CONFIGD_PATH Resolvable path to alternative svc.configd(1M) binary. 4777c478bd9Sstevel@tonic-gate */ 4787c478bd9Sstevel@tonic-gate void 4797c478bd9Sstevel@tonic-gate engine_init() 4807c478bd9Sstevel@tonic-gate { 4817c478bd9Sstevel@tonic-gate const char *cp; 4827c478bd9Sstevel@tonic-gate 4837c478bd9Sstevel@tonic-gate est = uu_zalloc(sizeof (engine_state_t)); 4847c478bd9Sstevel@tonic-gate 4857c478bd9Sstevel@tonic-gate est->sc_cmd_lineno = 1; 4867c478bd9Sstevel@tonic-gate est->sc_repo_pid = -1; 4877c478bd9Sstevel@tonic-gate 4887c478bd9Sstevel@tonic-gate cp = getenv("SVCCFG_REPOSITORY"); 4897c478bd9Sstevel@tonic-gate est->sc_repo_filename = cp ? safe_strdup(cp) : NULL; 4907c478bd9Sstevel@tonic-gate 4917c478bd9Sstevel@tonic-gate cp = getenv("SVCCFG_DOOR_PATH"); 4927c478bd9Sstevel@tonic-gate est->sc_repo_doordir = cp ? cp : "/var/run"; 4937c478bd9Sstevel@tonic-gate 4947c478bd9Sstevel@tonic-gate cp = getenv("SVCCFG_DOOR"); 4957c478bd9Sstevel@tonic-gate if (cp != NULL) { 4967c478bd9Sstevel@tonic-gate if (est->sc_repo_filename != NULL) { 4977c478bd9Sstevel@tonic-gate uu_warn(gettext("SVCCFG_DOOR unused when " 4987c478bd9Sstevel@tonic-gate "SVCCFG_REPOSITORY specified\n")); 4997c478bd9Sstevel@tonic-gate } else { 5007c478bd9Sstevel@tonic-gate est->sc_repo_doorname = safe_strdup(cp); 5017c478bd9Sstevel@tonic-gate } 5027c478bd9Sstevel@tonic-gate } 5037c478bd9Sstevel@tonic-gate 5047c478bd9Sstevel@tonic-gate cp = getenv("SVCCFG_CONFIGD_PATH"); 5057c478bd9Sstevel@tonic-gate est->sc_repo_server = cp ? cp : "/lib/svc/bin/svc.configd"; 5069444c26fSTom Whitten 507f329b923SSean Wilcox est->sc_miss_type = B_FALSE; 5089444c26fSTom Whitten est->sc_in_emi = 0; 5099444c26fSTom Whitten cp = getenv("SMF_FMRI"); 5109444c26fSTom Whitten if ((cp != NULL) && (strcmp(cp, SCF_INSTANCE_EMI) == 0)) 5119444c26fSTom Whitten est->sc_in_emi = 1; 5129444c26fSTom Whitten 5139444c26fSTom Whitten cp = smf_get_state(SCF_INSTANCE_FS_MINIMAL); 5149444c26fSTom Whitten if (cp && (strcmp(cp, SCF_STATE_STRING_ONLINE) == 0)) 5159444c26fSTom Whitten est->sc_fs_minimal = B_TRUE; 5169444c26fSTom Whitten free((void *) cp); 5177c478bd9Sstevel@tonic-gate } 5187c478bd9Sstevel@tonic-gate 5199444c26fSTom Whitten static int 5209444c26fSTom Whitten import_manifest_file(manifest_info_t *info, boolean_t validate, FILE *pout, 5219444c26fSTom Whitten uint_t flags) 5227c478bd9Sstevel@tonic-gate { 5237c478bd9Sstevel@tonic-gate bundle_t *b; 5241f6eb021SLiane Praza tmpl_errors_t *errs; 5259444c26fSTom Whitten const char *file; 5269444c26fSTom Whitten tmpl_validate_status_t vr; 5277c478bd9Sstevel@tonic-gate 5289444c26fSTom Whitten file = info->mi_path; 5297c478bd9Sstevel@tonic-gate 5309444c26fSTom Whitten /* Load the manifest */ 5317c478bd9Sstevel@tonic-gate b = internal_bundle_new(); 5327c478bd9Sstevel@tonic-gate 5333eae19d9Swesolows if (lxml_get_bundle_file(b, file, SVCCFG_OP_IMPORT) != 0) { 5347c478bd9Sstevel@tonic-gate internal_bundle_free(b); 5357c478bd9Sstevel@tonic-gate return (-1); 5367c478bd9Sstevel@tonic-gate } 5377c478bd9Sstevel@tonic-gate 5381f6eb021SLiane Praza /* Validate */ 5391f6eb021SLiane Praza if ((vr = tmpl_validate_bundle(b, &errs)) != TVS_SUCCESS) { 5401f6eb021SLiane Praza char *prefix; 5411f6eb021SLiane Praza 5421f6eb021SLiane Praza if ((validate == 0) || (vr == TVS_WARN)) { 5431f6eb021SLiane Praza prefix = gettext("Warning: "); 5441f6eb021SLiane Praza } else { 5451f6eb021SLiane Praza prefix = ""; 5461f6eb021SLiane Praza } 5471f6eb021SLiane Praza tmpl_errors_print(stderr, errs, prefix); 5481f6eb021SLiane Praza if (validate && (vr != TVS_WARN)) { 5491f6eb021SLiane Praza tmpl_errors_destroy(errs); 5509444c26fSTom Whitten semerr(gettext("Import of %s failed.\n"), 5519444c26fSTom Whitten info->mi_path); 5529444c26fSTom Whitten if (pout != NULL) { 5539444c26fSTom Whitten (void) fprintf(pout, gettext("WARNING: svccfg " 5549444c26fSTom Whitten "import of %s failed.\n"), info->mi_path); 5559444c26fSTom Whitten } 5569444c26fSTom Whitten 5571f6eb021SLiane Praza return (-1); 5581f6eb021SLiane Praza } 5591f6eb021SLiane Praza } 5601f6eb021SLiane Praza tmpl_errors_destroy(errs); 5611f6eb021SLiane Praza 5627c478bd9Sstevel@tonic-gate /* Import */ 5637c478bd9Sstevel@tonic-gate if (lscf_bundle_import(b, file, flags) != 0) { 5647c478bd9Sstevel@tonic-gate internal_bundle_free(b); 5659444c26fSTom Whitten semerr(gettext("Import of %s failed.\n"), info->mi_path); 5669444c26fSTom Whitten if (pout != NULL) { 5679444c26fSTom Whitten (void) fprintf(pout, gettext("WARNING: svccfg import " 5689444c26fSTom Whitten "of %s failed.\n"), info->mi_path); 5699444c26fSTom Whitten } 5707c478bd9Sstevel@tonic-gate return (-1); 5717c478bd9Sstevel@tonic-gate } 5727c478bd9Sstevel@tonic-gate 5737c478bd9Sstevel@tonic-gate internal_bundle_free(b); 5747c478bd9Sstevel@tonic-gate 5759444c26fSTom Whitten if (info->mi_prop) { 5767c478bd9Sstevel@tonic-gate char *errstr; 5777c478bd9Sstevel@tonic-gate 5789444c26fSTom Whitten if (mhash_store_entry(g_hndl, info->mi_prop, file, 5799444c26fSTom Whitten info->mi_hash, APPLY_NONE, &errstr)) { 5807c478bd9Sstevel@tonic-gate if (errstr) 5819444c26fSTom Whitten semerr(gettext("Could not store hash for %s. " 5829444c26fSTom Whitten "%s\n"), info->mi_path, errstr); 5837c478bd9Sstevel@tonic-gate else 5847c478bd9Sstevel@tonic-gate semerr(gettext("Unknown error from " 5859444c26fSTom Whitten "mhash_store_entry() for %s\n"), 5869444c26fSTom Whitten info->mi_path); 5877c478bd9Sstevel@tonic-gate } 5887c478bd9Sstevel@tonic-gate 5897c478bd9Sstevel@tonic-gate } 5907c478bd9Sstevel@tonic-gate 5917c478bd9Sstevel@tonic-gate return (0); 5927c478bd9Sstevel@tonic-gate } 5937c478bd9Sstevel@tonic-gate 5949444c26fSTom Whitten /* 5959444c26fSTom Whitten * Return values: 5969444c26fSTom Whitten * 1 No manifests need to be imported. 5979444c26fSTom Whitten * 0 Success 5989444c26fSTom Whitten * -1 Error 5999444c26fSTom Whitten * -2 Syntax error 6009444c26fSTom Whitten */ 6019444c26fSTom Whitten int 6029444c26fSTom Whitten engine_import(uu_list_t *args) 6039444c26fSTom Whitten { 6049444c26fSTom Whitten int argc, i, o; 6059444c26fSTom Whitten int dont_exit; 6069444c26fSTom Whitten int failed_manifests; 6079444c26fSTom Whitten int total_manifests; 6089444c26fSTom Whitten char *file; 6099444c26fSTom Whitten char **argv = NULL; 6109444c26fSTom Whitten string_list_t *slp; 6119444c26fSTom Whitten boolean_t validate = B_FALSE; 6129444c26fSTom Whitten uint_t flags = SCI_GENERALLAST; 6139444c26fSTom Whitten int dirarg = 0; 6149444c26fSTom Whitten int isdir; 6159444c26fSTom Whitten int rc = -1; 6169444c26fSTom Whitten struct stat sb; 6179444c26fSTom Whitten char **paths; 6189444c26fSTom Whitten manifest_info_t ***manifest_sets = NULL; 6199444c26fSTom Whitten manifest_info_t **manifests; 6209444c26fSTom Whitten char *progress_file = NULL; 6219444c26fSTom Whitten FILE *progress_out = NULL; 6229444c26fSTom Whitten int progress_count; 6239444c26fSTom Whitten int back_count; 6249444c26fSTom Whitten int count; 6259444c26fSTom Whitten int fm_flags; 6269444c26fSTom Whitten 6279444c26fSTom Whitten argc = uu_list_numnodes(args); 6289444c26fSTom Whitten if (argc < 1) 6299444c26fSTom Whitten return (-2); 6309444c26fSTom Whitten 6319444c26fSTom Whitten argv = calloc(argc + 1, sizeof (char *)); 6329444c26fSTom Whitten if (argv == NULL) 6339444c26fSTom Whitten uu_die(gettext("Out of memory.\n")); 6349444c26fSTom Whitten 6359444c26fSTom Whitten for (slp = uu_list_first(args), i = 0; 6369444c26fSTom Whitten slp != NULL; 6379444c26fSTom Whitten slp = uu_list_next(args, slp), ++i) 6389444c26fSTom Whitten argv[i] = slp->str; 6399444c26fSTom Whitten 6409444c26fSTom Whitten argv[i] = NULL; 6419444c26fSTom Whitten 6429444c26fSTom Whitten opterr = 0; 6439444c26fSTom Whitten optind = 0; /* Remember, no argv[0]. */ 6449444c26fSTom Whitten for (;;) { 6459444c26fSTom Whitten o = getopt(argc, argv, "np:V"); 6469444c26fSTom Whitten if (o == -1) 6479444c26fSTom Whitten break; 6489444c26fSTom Whitten 6499444c26fSTom Whitten switch (o) { 6509444c26fSTom Whitten case 'n': 6519444c26fSTom Whitten flags |= SCI_NOREFRESH; 6529444c26fSTom Whitten break; 6539444c26fSTom Whitten 6549444c26fSTom Whitten case 'p': 6559444c26fSTom Whitten progress_file = optarg; 6569444c26fSTom Whitten break; 6579444c26fSTom Whitten 6589444c26fSTom Whitten case 'V': 6599444c26fSTom Whitten validate = B_TRUE; 6609444c26fSTom Whitten break; 6619444c26fSTom Whitten 6629444c26fSTom Whitten case '?': 6639444c26fSTom Whitten free(argv); 6649444c26fSTom Whitten return (-2); 6659444c26fSTom Whitten 6669444c26fSTom Whitten default: 6679444c26fSTom Whitten bad_error("getopt", o); 6689444c26fSTom Whitten } 6699444c26fSTom Whitten } 6709444c26fSTom Whitten 6719444c26fSTom Whitten argc -= optind; 6729444c26fSTom Whitten if (argc < 1) { 6739444c26fSTom Whitten free(argv); 6749444c26fSTom Whitten return (-2); 6759444c26fSTom Whitten } 6769444c26fSTom Whitten 6779444c26fSTom Whitten /* Open device for progress messages */ 6789444c26fSTom Whitten if (progress_file != NULL) { 6799444c26fSTom Whitten if (strcmp(progress_file, "-") == 0) { 6809444c26fSTom Whitten progress_out = stdout; 6819444c26fSTom Whitten } else { 6829444c26fSTom Whitten progress_out = fopen(progress_file, "w"); 6839444c26fSTom Whitten if (progress_out == NULL) { 6849444c26fSTom Whitten semerr(gettext("Unable to open %s for " 6859444c26fSTom Whitten "progress reporting. %s\n"), 6869444c26fSTom Whitten progress_file, strerror(errno)); 6879444c26fSTom Whitten goto out; 6889444c26fSTom Whitten } 6899444c26fSTom Whitten setbuf(progress_out, NULL); 6909444c26fSTom Whitten } 6919444c26fSTom Whitten } 6929444c26fSTom Whitten 6939444c26fSTom Whitten paths = argv+optind; 6949444c26fSTom Whitten manifest_sets = safe_malloc(argc * sizeof (*manifest_sets)); 6959444c26fSTom Whitten 6969444c26fSTom Whitten /* If we're in interactive mode, force strict validation. */ 6979444c26fSTom Whitten if (est->sc_cmd_flags & SC_CMD_IACTIVE) 6989444c26fSTom Whitten validate = B_TRUE; 6999444c26fSTom Whitten 7009444c26fSTom Whitten lscf_prep_hndl(); 7019444c26fSTom Whitten 7029444c26fSTom Whitten /* Determine which manifests must be imported. */ 7039444c26fSTom Whitten 7049444c26fSTom Whitten total_manifests = 0; 7059444c26fSTom Whitten for (i = 0; i < argc; i++) { 7069444c26fSTom Whitten file = *(paths + i); 7079444c26fSTom Whitten fm_flags = CHECKHASH; 7089444c26fSTom Whitten 7099444c26fSTom Whitten /* Determine if argument is a directory or file. */ 7109444c26fSTom Whitten if (stat(file, &sb) == -1) { 7119444c26fSTom Whitten semerr(gettext("Unable to stat file %s. %s\n"), file, 7129444c26fSTom Whitten strerror(errno)); 7139444c26fSTom Whitten goto out; 7149444c26fSTom Whitten } 7159444c26fSTom Whitten if (sb.st_mode & S_IFDIR) { 7169444c26fSTom Whitten fm_flags |= CHECKEXT; 7179444c26fSTom Whitten dirarg = 1; 7189444c26fSTom Whitten isdir = 1; 7199444c26fSTom Whitten } else if (sb.st_mode & S_IFREG) { 7209444c26fSTom Whitten isdir = 0; 7219444c26fSTom Whitten } else { 7229444c26fSTom Whitten semerr(gettext("%s is not a directory or regular " 7239444c26fSTom Whitten "file\n"), file); 7249444c26fSTom Whitten goto out; 7259444c26fSTom Whitten } 7269444c26fSTom Whitten 7279444c26fSTom Whitten /* Get list of manifests that we should import for this path. */ 728293e3ab3STruong Q. Nguyen if ((count = find_manifests(g_hndl, file, &manifests, 729293e3ab3STruong Q. Nguyen fm_flags)) < 0) { 7309444c26fSTom Whitten if (isdir) { 7319444c26fSTom Whitten semerr(gettext("Could not hash directory %s\n"), 7329444c26fSTom Whitten file); 7339444c26fSTom Whitten } else { 7349444c26fSTom Whitten semerr(gettext("Could not hash file %s\n"), 7359444c26fSTom Whitten file); 7369444c26fSTom Whitten } 7379444c26fSTom Whitten free_manifest_array(manifests); 7389444c26fSTom Whitten goto out; 7399444c26fSTom Whitten } 7409444c26fSTom Whitten total_manifests += count; 7419444c26fSTom Whitten manifest_sets[i] = manifests; 7429444c26fSTom Whitten } 7439444c26fSTom Whitten 7449444c26fSTom Whitten if (total_manifests == 0) { 7459444c26fSTom Whitten /* No manifests to process. */ 7469444c26fSTom Whitten if (g_verbose) { 7479444c26fSTom Whitten warn(gettext("No changes were necessary\n")); 7489444c26fSTom Whitten } 7499444c26fSTom Whitten rc = 1; 7509444c26fSTom Whitten goto out; 7519444c26fSTom Whitten } 7529444c26fSTom Whitten 7539444c26fSTom Whitten /* 7549444c26fSTom Whitten * If we're processing more than one file, we don't want to exit if 7559444c26fSTom Whitten * we encounter an error. We should go ahead and process all of 7569444c26fSTom Whitten * the manifests. 7579444c26fSTom Whitten */ 7589444c26fSTom Whitten dont_exit = est->sc_cmd_flags & SC_CMD_DONT_EXIT; 7599444c26fSTom Whitten if (total_manifests > 1) 7609444c26fSTom Whitten est->sc_cmd_flags |= SC_CMD_DONT_EXIT; 7619444c26fSTom Whitten 7629444c26fSTom Whitten if (progress_out != NULL) 7639444c26fSTom Whitten (void) fprintf(progress_out, 7649444c26fSTom Whitten "Loading smf(5) service descriptions: "); 7659444c26fSTom Whitten 7669444c26fSTom Whitten failed_manifests = 0; 7679444c26fSTom Whitten progress_count = 0; 7689444c26fSTom Whitten for (i = 0; i < argc; i++) { 7699444c26fSTom Whitten manifests = manifest_sets[i]; 7709444c26fSTom Whitten if (manifests == NULL) 7719444c26fSTom Whitten continue; 7729444c26fSTom Whitten for (; *manifests != NULL; manifests++) { 7739444c26fSTom Whitten progress_count++; 7749444c26fSTom Whitten if (progress_out != NULL) { 7759444c26fSTom Whitten back_count = fprintf(progress_out, "%d/%d", 7769444c26fSTom Whitten progress_count, total_manifests); 7779444c26fSTom Whitten while (back_count-- > 0) { 7789444c26fSTom Whitten (void) fputc('\b', progress_out); 7799444c26fSTom Whitten } 7809444c26fSTom Whitten } 7819444c26fSTom Whitten if (import_manifest_file(*manifests, validate, 7829444c26fSTom Whitten progress_out, flags) != 0) { 7839444c26fSTom Whitten failed_manifests++; 7849444c26fSTom Whitten } 7859444c26fSTom Whitten } 7869444c26fSTom Whitten } 7879444c26fSTom Whitten if (progress_out != NULL) 7889444c26fSTom Whitten (void) fputc('\n', progress_out); 7899444c26fSTom Whitten 7909444c26fSTom Whitten if ((total_manifests > 1) && (dont_exit == 0)) 7919444c26fSTom Whitten est->sc_cmd_flags &= ~SC_CMD_DONT_EXIT; 7929444c26fSTom Whitten 7939444c26fSTom Whitten if (dirarg && total_manifests > 0) { 7949444c26fSTom Whitten char *msg; 7959444c26fSTom Whitten 7969444c26fSTom Whitten msg = "Loaded %d smf(5) service descriptions\n"; 7979444c26fSTom Whitten warn(gettext(msg), progress_count); 7989444c26fSTom Whitten 7999444c26fSTom Whitten if (failed_manifests) { 8009444c26fSTom Whitten msg = "%d smf(5) service descriptions failed to load\n"; 8019444c26fSTom Whitten warn(gettext(msg), failed_manifests); 8029444c26fSTom Whitten } 8039444c26fSTom Whitten } 8049444c26fSTom Whitten 8059444c26fSTom Whitten if (failed_manifests > 0) 8069444c26fSTom Whitten goto out; 8079444c26fSTom Whitten 8089444c26fSTom Whitten if (g_verbose) 8099444c26fSTom Whitten warn(gettext("Successful import.\n")); 8109444c26fSTom Whitten rc = 0; 8119444c26fSTom Whitten 8129444c26fSTom Whitten out: 8139444c26fSTom Whitten if ((progress_out != NULL) && (progress_out != stdout)) 8149444c26fSTom Whitten (void) fclose(progress_out); 8159444c26fSTom Whitten free(argv); 8169444c26fSTom Whitten if (manifest_sets != NULL) { 8179444c26fSTom Whitten for (i = 0; i < argc; i++) { 8189444c26fSTom Whitten free_manifest_array(manifest_sets[i]); 8199444c26fSTom Whitten } 8209444c26fSTom Whitten free(manifest_sets); 8219444c26fSTom Whitten } 8229444c26fSTom Whitten return (rc); 8239444c26fSTom Whitten } 8249444c26fSTom Whitten 8259444c26fSTom Whitten /* 8269444c26fSTom Whitten * Walk each service and get its manifest file. 8279444c26fSTom Whitten * 8289444c26fSTom Whitten * If the file exists check instance support, and cleanup any 8299444c26fSTom Whitten * stale instances. 8309444c26fSTom Whitten * 8319444c26fSTom Whitten * If the file doesn't exist tear down the service and/or instances 8329444c26fSTom Whitten * that are no longer supported by files. 8339444c26fSTom Whitten */ 8349444c26fSTom Whitten int 8359444c26fSTom Whitten engine_cleanup(int flags) 8369444c26fSTom Whitten { 8379444c26fSTom Whitten boolean_t activity = B_TRUE; 838*8c10095fSAlbert Lee int dont_exit; 8399444c26fSTom Whitten int r = -1; 8409444c26fSTom Whitten 8419444c26fSTom Whitten lscf_prep_hndl(); 8429444c26fSTom Whitten 8439444c26fSTom Whitten if (flags == 1) { 8449444c26fSTom Whitten activity = B_FALSE; 8459444c26fSTom Whitten } 8469444c26fSTom Whitten 847*8c10095fSAlbert Lee dont_exit = est->sc_cmd_flags & SC_CMD_DONT_EXIT; 848*8c10095fSAlbert Lee est->sc_cmd_flags |= SC_CMD_DONT_EXIT; 849*8c10095fSAlbert Lee 8509444c26fSTom Whitten if (scf_walk_fmri(g_hndl, 0, NULL, SCF_WALK_SERVICE|SCF_WALK_NOINSTANCE, 8519444c26fSTom Whitten lscf_service_cleanup, (void *)activity, NULL, 8529444c26fSTom Whitten uu_warn) == SCF_SUCCESS) 8539444c26fSTom Whitten r = 0; 8549444c26fSTom Whitten 855*8c10095fSAlbert Lee if (dont_exit == 0) 856*8c10095fSAlbert Lee est->sc_cmd_flags &= ~SC_CMD_DONT_EXIT; 857*8c10095fSAlbert Lee 8589444c26fSTom Whitten (void) lscf_hash_cleanup(); 8599444c26fSTom Whitten 8609444c26fSTom Whitten return (r); 8619444c26fSTom Whitten } 8629444c26fSTom Whitten 863adfc3118STruong Nguyen static int 864adfc3118STruong Nguyen apply_profile(manifest_info_t *info, int apply_changes) 8657c478bd9Sstevel@tonic-gate { 866adfc3118STruong Nguyen bundle_t *b = internal_bundle_new(); 8677c478bd9Sstevel@tonic-gate 868adfc3118STruong Nguyen if (lxml_get_bundle_file(b, info->mi_path, SVCCFG_OP_APPLY) != 0) { 8697c478bd9Sstevel@tonic-gate internal_bundle_free(b); 8707c478bd9Sstevel@tonic-gate return (-1); 8717c478bd9Sstevel@tonic-gate } 8727c478bd9Sstevel@tonic-gate 873687293e1SAntonello Cruz if (!apply_changes) { /* we don't want to apply, just test */ 874687293e1SAntonello Cruz internal_bundle_free(b); 875687293e1SAntonello Cruz return (0); 876687293e1SAntonello Cruz } 877687293e1SAntonello Cruz 878adfc3118STruong Nguyen if (lscf_bundle_apply(b, info->mi_path) != 0) { 8797c478bd9Sstevel@tonic-gate internal_bundle_free(b); 8807c478bd9Sstevel@tonic-gate return (-1); 8817c478bd9Sstevel@tonic-gate } 8827c478bd9Sstevel@tonic-gate 8837c478bd9Sstevel@tonic-gate internal_bundle_free(b); 8847c478bd9Sstevel@tonic-gate 885adfc3118STruong Nguyen if (info->mi_prop) { 8869444c26fSTom Whitten apply_action_t apply; 8877c478bd9Sstevel@tonic-gate char *errstr; 8889444c26fSTom Whitten 8899444c26fSTom Whitten apply = (est->sc_in_emi == 1) ? APPLY_LATE : APPLY_NONE; 890adfc3118STruong Nguyen if (mhash_store_entry(g_hndl, info->mi_prop, info->mi_path, 891adfc3118STruong Nguyen info->mi_hash, apply, &errstr)) { 8927c478bd9Sstevel@tonic-gate semerr(errstr); 8939444c26fSTom Whitten } 8947c478bd9Sstevel@tonic-gate } 8957c478bd9Sstevel@tonic-gate 8967c478bd9Sstevel@tonic-gate return (0); 8977c478bd9Sstevel@tonic-gate } 8987c478bd9Sstevel@tonic-gate 8997c478bd9Sstevel@tonic-gate int 900adfc3118STruong Nguyen engine_apply(const char *file, int apply_changes) 901adfc3118STruong Nguyen { 902adfc3118STruong Nguyen int rc = 0; 903adfc3118STruong Nguyen int isdir; 904adfc3118STruong Nguyen int dont_exit; 905adfc3118STruong Nguyen int profile_count; 906adfc3118STruong Nguyen int fm_flags; 907adfc3118STruong Nguyen struct stat sb; 908adfc3118STruong Nguyen manifest_info_t **profiles = NULL; 909adfc3118STruong Nguyen manifest_info_t **entry; 910adfc3118STruong Nguyen manifest_info_t *pfile; 911adfc3118STruong Nguyen 912adfc3118STruong Nguyen lscf_prep_hndl(); 913adfc3118STruong Nguyen 914adfc3118STruong Nguyen /* Determine which profile(s) must be applied. */ 915adfc3118STruong Nguyen 916adfc3118STruong Nguyen profile_count = 0; 917adfc3118STruong Nguyen fm_flags = BUNDLE_PROF | CHECKHASH; 918adfc3118STruong Nguyen 919adfc3118STruong Nguyen /* Determine if argument is a directory or file. */ 920adfc3118STruong Nguyen if (stat(file, &sb) == -1) { 921adfc3118STruong Nguyen semerr(gettext("Unable to stat file %s. %s\n"), file, 922adfc3118STruong Nguyen strerror(errno)); 923adfc3118STruong Nguyen rc = -1; 924adfc3118STruong Nguyen goto out; 925adfc3118STruong Nguyen } 926adfc3118STruong Nguyen 927adfc3118STruong Nguyen if (sb.st_mode & S_IFDIR) { 928adfc3118STruong Nguyen fm_flags |= CHECKEXT; 929adfc3118STruong Nguyen isdir = 1; 930adfc3118STruong Nguyen } else if (sb.st_mode & S_IFREG) { 931adfc3118STruong Nguyen isdir = 0; 932adfc3118STruong Nguyen } else { 933adfc3118STruong Nguyen semerr(gettext("%s is not a directory or regular " 934adfc3118STruong Nguyen "file\n"), file); 935adfc3118STruong Nguyen rc = -1; 936adfc3118STruong Nguyen goto out; 937adfc3118STruong Nguyen } 938adfc3118STruong Nguyen 939adfc3118STruong Nguyen /* Get list of profiles to be applied. */ 940293e3ab3STruong Q. Nguyen if ((profile_count = find_manifests(g_hndl, file, &profiles, 941293e3ab3STruong Q. Nguyen fm_flags)) < 0) { 942293e3ab3STruong Q. Nguyen 943adfc3118STruong Nguyen if (isdir) { 944adfc3118STruong Nguyen semerr(gettext("Could not hash directory %s\n"), file); 945adfc3118STruong Nguyen } else { 946adfc3118STruong Nguyen semerr(gettext("Could not hash file %s\n"), file); 947adfc3118STruong Nguyen } 948adfc3118STruong Nguyen rc = -1; 949adfc3118STruong Nguyen goto out; 950adfc3118STruong Nguyen } 951adfc3118STruong Nguyen 952adfc3118STruong Nguyen if (profile_count == 0) { 953adfc3118STruong Nguyen /* No profiles to process. */ 954adfc3118STruong Nguyen if (g_verbose) { 955adfc3118STruong Nguyen warn(gettext("No changes were necessary\n")); 956adfc3118STruong Nguyen } 957adfc3118STruong Nguyen goto out; 958adfc3118STruong Nguyen } 959adfc3118STruong Nguyen 960adfc3118STruong Nguyen /* 961adfc3118STruong Nguyen * We don't want to exit if we encounter an error. We should go ahead 962adfc3118STruong Nguyen * and process all of the profiles. 963adfc3118STruong Nguyen */ 964adfc3118STruong Nguyen dont_exit = est->sc_cmd_flags & SC_CMD_DONT_EXIT; 965adfc3118STruong Nguyen est->sc_cmd_flags |= SC_CMD_DONT_EXIT; 966adfc3118STruong Nguyen 967adfc3118STruong Nguyen for (entry = profiles; *entry != NULL; entry++) { 968adfc3118STruong Nguyen pfile = *entry; 969adfc3118STruong Nguyen 970adfc3118STruong Nguyen if (apply_profile(pfile, apply_changes) == 0) { 971adfc3118STruong Nguyen if (g_verbose) { 972adfc3118STruong Nguyen warn(gettext("Successfully applied: %s\n"), 973adfc3118STruong Nguyen pfile->mi_path); 974adfc3118STruong Nguyen } 975adfc3118STruong Nguyen } else { 976adfc3118STruong Nguyen warn(gettext("WARNING: Failed to apply %s\n"), 977adfc3118STruong Nguyen pfile->mi_path); 978adfc3118STruong Nguyen rc = -1; 979adfc3118STruong Nguyen } 980adfc3118STruong Nguyen } 981adfc3118STruong Nguyen 982adfc3118STruong Nguyen if (dont_exit == 0) 983adfc3118STruong Nguyen est->sc_cmd_flags &= ~SC_CMD_DONT_EXIT; 984adfc3118STruong Nguyen 985adfc3118STruong Nguyen /* exit(1) appropriately if any profile failed to be applied. */ 986adfc3118STruong Nguyen if ((rc == -1) && 987adfc3118STruong Nguyen (est->sc_cmd_flags & (SC_CMD_IACTIVE | SC_CMD_DONT_EXIT)) == 0) { 988adfc3118STruong Nguyen free_manifest_array(profiles); 989adfc3118STruong Nguyen exit(1); 990adfc3118STruong Nguyen } 991adfc3118STruong Nguyen 992adfc3118STruong Nguyen out: 993adfc3118STruong Nguyen free_manifest_array(profiles); 994adfc3118STruong Nguyen return (rc); 995adfc3118STruong Nguyen } 996adfc3118STruong Nguyen 997adfc3118STruong Nguyen int 9983eae19d9Swesolows engine_restore(const char *file) 9993eae19d9Swesolows { 10003eae19d9Swesolows bundle_t *b; 10013eae19d9Swesolows 10023eae19d9Swesolows lscf_prep_hndl(); 10033eae19d9Swesolows 10043eae19d9Swesolows b = internal_bundle_new(); 10053eae19d9Swesolows 10063eae19d9Swesolows if (lxml_get_bundle_file(b, file, SVCCFG_OP_RESTORE) != 0) { 10073eae19d9Swesolows internal_bundle_free(b); 10083eae19d9Swesolows return (-1); 10093eae19d9Swesolows } 10103eae19d9Swesolows 10113eae19d9Swesolows if (lscf_bundle_import(b, file, SCI_NOSNAP) != 0) { 10123eae19d9Swesolows internal_bundle_free(b); 10133eae19d9Swesolows return (-1); 10143eae19d9Swesolows } 10153eae19d9Swesolows 10163eae19d9Swesolows internal_bundle_free(b); 10173eae19d9Swesolows 10183eae19d9Swesolows return (0); 10193eae19d9Swesolows } 10203eae19d9Swesolows 10213eae19d9Swesolows int 10227c478bd9Sstevel@tonic-gate engine_set(uu_list_t *args) 10237c478bd9Sstevel@tonic-gate { 10247c478bd9Sstevel@tonic-gate uu_list_walk_t *walk; 10257c478bd9Sstevel@tonic-gate string_list_t *slp; 10267c478bd9Sstevel@tonic-gate 10277c478bd9Sstevel@tonic-gate if (uu_list_first(args) == NULL) { 10287c478bd9Sstevel@tonic-gate /* Display current options. */ 10297c478bd9Sstevel@tonic-gate if (!g_verbose) 10307c478bd9Sstevel@tonic-gate (void) fputs("no", stdout); 10317c478bd9Sstevel@tonic-gate (void) puts("verbose"); 10327c478bd9Sstevel@tonic-gate 10337c478bd9Sstevel@tonic-gate return (0); 10347c478bd9Sstevel@tonic-gate } 10357c478bd9Sstevel@tonic-gate 10367c478bd9Sstevel@tonic-gate walk = uu_list_walk_start(args, UU_DEFAULT); 10377c478bd9Sstevel@tonic-gate if (walk == NULL) 10387c478bd9Sstevel@tonic-gate uu_die(gettext("Couldn't read arguments")); 10397c478bd9Sstevel@tonic-gate 10407c478bd9Sstevel@tonic-gate /* Use getopt? */ 10417c478bd9Sstevel@tonic-gate for (slp = uu_list_walk_next(walk); 10427c478bd9Sstevel@tonic-gate slp != NULL; 10437c478bd9Sstevel@tonic-gate slp = uu_list_walk_next(walk)) { 10447c478bd9Sstevel@tonic-gate if (slp->str[0] == '-') { 10457c478bd9Sstevel@tonic-gate char *op; 10467c478bd9Sstevel@tonic-gate 10477c478bd9Sstevel@tonic-gate for (op = &slp->str[1]; *op != '\0'; ++op) { 10487c478bd9Sstevel@tonic-gate switch (*op) { 10497c478bd9Sstevel@tonic-gate case 'v': 10507c478bd9Sstevel@tonic-gate g_verbose = 1; 10517c478bd9Sstevel@tonic-gate break; 10527c478bd9Sstevel@tonic-gate 10537c478bd9Sstevel@tonic-gate case 'V': 10547c478bd9Sstevel@tonic-gate g_verbose = 0; 10557c478bd9Sstevel@tonic-gate break; 10567c478bd9Sstevel@tonic-gate 10577c478bd9Sstevel@tonic-gate default: 10587c478bd9Sstevel@tonic-gate warn(gettext("Unknown option -%c.\n"), 10597c478bd9Sstevel@tonic-gate *op); 10607c478bd9Sstevel@tonic-gate } 10617c478bd9Sstevel@tonic-gate } 10627c478bd9Sstevel@tonic-gate } else { 10637c478bd9Sstevel@tonic-gate warn(gettext("No non-flag arguments defined.\n")); 10647c478bd9Sstevel@tonic-gate } 10657c478bd9Sstevel@tonic-gate } 10667c478bd9Sstevel@tonic-gate 10677c478bd9Sstevel@tonic-gate return (0); 10687c478bd9Sstevel@tonic-gate } 10697c478bd9Sstevel@tonic-gate 10707c478bd9Sstevel@tonic-gate void 10717c478bd9Sstevel@tonic-gate help(int com) 10727c478bd9Sstevel@tonic-gate { 10737c478bd9Sstevel@tonic-gate int i; 10747c478bd9Sstevel@tonic-gate 10757c478bd9Sstevel@tonic-gate if (com == 0) { 10767c478bd9Sstevel@tonic-gate warn(gettext("General commands: help set repository end\n" 10777c478bd9Sstevel@tonic-gate "Manifest commands: inventory validate import export " 10787c478bd9Sstevel@tonic-gate "archive\n" 10797c478bd9Sstevel@tonic-gate "Profile commands: apply extract\n" 10801f6eb021SLiane Praza "Entity commands: list select unselect add delete " 10811f6eb021SLiane Praza "describe\n" 10827c478bd9Sstevel@tonic-gate "Snapshot commands: listsnap selectsnap revert\n" 1083347a77f2Samaguire "Instance commands: refresh\n" 10847c478bd9Sstevel@tonic-gate "Property group commands: listpg addpg delpg\n" 10857c478bd9Sstevel@tonic-gate "Property commands: listprop setprop delprop editprop\n" 10867c478bd9Sstevel@tonic-gate "Property value commands: addpropvalue delpropvalue " 1087f6e214c7SGavin Maltby "setenv unsetenv\n" 1088f6e214c7SGavin Maltby "Notification parameters: " 1089f6e214c7SGavin Maltby "listnotify setnotify delnotify\n")); 10907c478bd9Sstevel@tonic-gate return; 10917c478bd9Sstevel@tonic-gate } 10927c478bd9Sstevel@tonic-gate 10937c478bd9Sstevel@tonic-gate for (i = 0; help_messages[i].message != NULL; ++i) { 10947c478bd9Sstevel@tonic-gate if (help_messages[i].token == com) { 10957c478bd9Sstevel@tonic-gate warn(gettext("Usage: %s\n"), 10967c478bd9Sstevel@tonic-gate gettext(help_messages[i].message)); 10977c478bd9Sstevel@tonic-gate return; 10987c478bd9Sstevel@tonic-gate } 10997c478bd9Sstevel@tonic-gate } 11007c478bd9Sstevel@tonic-gate 11017c478bd9Sstevel@tonic-gate warn(gettext("Unknown command.\n")); 11027c478bd9Sstevel@tonic-gate } 1103