6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright (c) 2015, Joyent, Inc. All rights reserved.
26 */
27
28 /*
29 * Service state explanation. For select services, display a description, the
30 * state, and possibly why the service is in that state, what's causing it to
31 * be in that state, and what other services it is keeping offline (impact).
32 *
33 * Explaining states other than offline is easy. For maintenance and
34 * degraded, we just use the auxiliary state. For offline, we must determine
35 * which dependencies are unsatisfied and recurse. If a causal service is not
36 * offline, then a svcptr to it is added to the offline service's causes list.
37 * If a causal service is offline, then we recurse to determine its causes and
38 * merge them into the causes list of the service in question (see
39 * add_causes()). Note that by adding a self-pointing svcptr to the causes
40 * lists of services which are not offline or are offline for unknown reasons,
41 * we can always merge the unsatisfied dependency's causes into the
42 * dependent's list.
43 *
44 * Computing an impact list is more involved because the dependencies in the
45 * repository are unidirectional; it requires determining the causes of all
1179 (void) fprintf(stderr, gettext("Dependency cycle detected:\n"
1180 " svc:/%s:%s\n"), svcp->svcname, svcp->instname);
1181 return ((int)canfailp != 0 ? UU_WALK_ERROR : UU_WALK_NEXT);
1182 }
1183
1184 if (svcp->causes != NULL)
1185 return (UU_WALK_NEXT);
1186
1187 svcp->causes = uu_list_create(svcptrs, svcp, UU_LIST_DEBUG);
1188 svcp->baddeps = uu_list_create(deps, svcp, UU_LIST_DEBUG);
1189 if (svcp->causes == NULL || svcp->baddeps == NULL)
1190 uu_die(emsg_nomem);
1191
1192 if (inst_running(svcp) ||
1193 strcmp(svcp->state, SCF_STATE_STRING_UNINIT) == 0) {
1194 /*
1195 * If we're running, add a self-pointer in case we're
1196 * excluding another service.
1197 */
1198 add_svcptr(svcp->causes, svcp);
1199 return (UU_WALK_NEXT);
1200 }
1201
1202 if (strcmp(svcp->state, SCF_STATE_STRING_MAINT) == 0) {
1203 add_svcptr(svcp->causes, svcp);
1204 add_svcptr(g_causes, svcp);
1205 return (UU_WALK_NEXT);
1206 }
1207
1208 if (strcmp(svcp->state, SCF_STATE_STRING_DISABLED) == 0) {
1209 add_svcptr(svcp->causes, svcp);
1210 if (svcp->enabled != 0)
1211 add_svcptr(g_causes, svcp);
1212
1213 return (UU_WALK_NEXT);
1214 }
1215
1216 if (strcmp(svcp->state, SCF_STATE_STRING_OFFLINE) != 0) {
1217 (void) fprintf(stderr,
1218 gettext("svc:/%s:%s has invalid state \"%s\".\n"),
1471 ip->summary = gettext("is in an invalid state.");
1472 }
1473 }
1474
1475 static void
1476 print_method_failure(const inst_t *ip, const char **dcp)
1477 {
1478 char buf[50];
1479 int stat = ip->start_method_waitstatus;
1480
1481 if (stat != 0) {
1482 if (WIFEXITED(stat)) {
1483 if (WEXITSTATUS(stat) == SMF_EXIT_ERR_CONFIG) {
1484 (void) strlcpy(buf, gettext(
1485 "exited with $SMF_EXIT_ERR_CONFIG"),
1486 sizeof (buf));
1487 } else if (WEXITSTATUS(stat) == SMF_EXIT_ERR_FATAL) {
1488 (void) strlcpy(buf, gettext(
1489 "exited with $SMF_EXIT_ERR_FATAL"),
1490 sizeof (buf));
1491 } else {
1492 (void) snprintf(buf, sizeof (buf),
1493 gettext("exited with status %d"),
1494 WEXITSTATUS(stat));
1495 }
1496 } else if (WIFSIGNALED(stat)) {
1497 if (WCOREDUMP(stat)) {
1498 if (strsignal(WTERMSIG(stat)) != NULL)
1499 (void) snprintf(buf, sizeof (buf),
1500 gettext("dumped core on %s (%d)"),
1501 strsignal(WTERMSIG(stat)),
1502 WTERMSIG(stat));
1503 else
1504 (void) snprintf(buf, sizeof (buf),
1505 gettext("dumped core signal %d"),
1506 WTERMSIG(stat));
1507 } else {
1508 if (strsignal(WTERMSIG(stat)) != NULL) {
1509 (void) snprintf(buf, sizeof (buf),
1510 gettext("died on %s (%d)"),
1791 }
1792
1793 } else if (strcmp(svcp->state, SCF_STATE_STRING_OFFLINE) == 0) {
1794 if (strcmp(svcp->next_state, SCF_STATE_STRING_ONLINE) == 0) {
1795 (void) puts(gettext(
1796 "Reason: Start method is running."));
1797 dc = DC_STARTING;
1798 } else if (strcmp(svcp->next_state, SCF_STATE_STRING_NONE) ==
1799 0) {
1800 print_dependency_reasons(svcp, verbose);
1801 /* Function prints diagcodes. */
1802 return;
1803 } else {
1804 (void) printf(gettext(
1805 "Reason: Transitioning to state %s.\n"),
1806 svcp->next_state);
1807 dc = DC_TRANSITION;
1808 }
1809
1810 } else if (strcmp(svcp->state, SCF_STATE_STRING_DEGRADED) == 0) {
1811 (void) puts(gettext("Reason: Degraded by an administrator."));
1812 dc = DC_ADMINDEGR;
1813
1814 } else {
1815 (void) printf(gettext("Reason: Not in valid state (%s).\n"),
1816 svcp->state);
1817 dc = DC_INVALIDSTATE;
1818 }
1819
1820 diagcode:
1821 if (g_msgbase != NULL)
1822 (void) printf(gettext(" See: %s%s\n"), g_msgbase, dc);
1823 }
1824
1825 static void
1826 print_manpage(int verbose)
1827 {
1828 static char *title = NULL;
1829 static char *section = NULL;
1830
1831 if (title == NULL) {
1832 title = safe_malloc(g_value_sz);
1833 section = safe_malloc(g_value_sz);
1834 }
1835
1836 if (pg_get_single_val(g_pg, SCF_PROPERTY_TM_TITLE, SCF_TYPE_ASTRING,
1837 (void *)title, g_value_sz, 0) != 0)
1838 return;
1839
1840 if (pg_get_single_val(g_pg, SCF_PROPERTY_TM_SECTION,
1841 SCF_TYPE_ASTRING, (void *)section, g_value_sz, 0) != 0)
|
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright (c) 2015, Joyent, Inc. All rights reserved.
26 * Copyright 2017 RackTop Systems.
27 */
28
29 /*
30 * Service state explanation. For select services, display a description, the
31 * state, and possibly why the service is in that state, what's causing it to
32 * be in that state, and what other services it is keeping offline (impact).
33 *
34 * Explaining states other than offline is easy. For maintenance and
35 * degraded, we just use the auxiliary state. For offline, we must determine
36 * which dependencies are unsatisfied and recurse. If a causal service is not
37 * offline, then a svcptr to it is added to the offline service's causes list.
38 * If a causal service is offline, then we recurse to determine its causes and
39 * merge them into the causes list of the service in question (see
40 * add_causes()). Note that by adding a self-pointing svcptr to the causes
41 * lists of services which are not offline or are offline for unknown reasons,
42 * we can always merge the unsatisfied dependency's causes into the
43 * dependent's list.
44 *
45 * Computing an impact list is more involved because the dependencies in the
46 * repository are unidirectional; it requires determining the causes of all
1180 (void) fprintf(stderr, gettext("Dependency cycle detected:\n"
1181 " svc:/%s:%s\n"), svcp->svcname, svcp->instname);
1182 return ((int)canfailp != 0 ? UU_WALK_ERROR : UU_WALK_NEXT);
1183 }
1184
1185 if (svcp->causes != NULL)
1186 return (UU_WALK_NEXT);
1187
1188 svcp->causes = uu_list_create(svcptrs, svcp, UU_LIST_DEBUG);
1189 svcp->baddeps = uu_list_create(deps, svcp, UU_LIST_DEBUG);
1190 if (svcp->causes == NULL || svcp->baddeps == NULL)
1191 uu_die(emsg_nomem);
1192
1193 if (inst_running(svcp) ||
1194 strcmp(svcp->state, SCF_STATE_STRING_UNINIT) == 0) {
1195 /*
1196 * If we're running, add a self-pointer in case we're
1197 * excluding another service.
1198 */
1199 add_svcptr(svcp->causes, svcp);
1200 if (strcmp(svcp->state, SCF_STATE_STRING_DEGRADED) == 0)
1201 add_svcptr(g_causes, svcp);
1202
1203 return (UU_WALK_NEXT);
1204 }
1205
1206 if (strcmp(svcp->state, SCF_STATE_STRING_MAINT) == 0) {
1207 add_svcptr(svcp->causes, svcp);
1208 add_svcptr(g_causes, svcp);
1209 return (UU_WALK_NEXT);
1210 }
1211
1212 if (strcmp(svcp->state, SCF_STATE_STRING_DISABLED) == 0) {
1213 add_svcptr(svcp->causes, svcp);
1214 if (svcp->enabled != 0)
1215 add_svcptr(g_causes, svcp);
1216
1217 return (UU_WALK_NEXT);
1218 }
1219
1220 if (strcmp(svcp->state, SCF_STATE_STRING_OFFLINE) != 0) {
1221 (void) fprintf(stderr,
1222 gettext("svc:/%s:%s has invalid state \"%s\".\n"),
1475 ip->summary = gettext("is in an invalid state.");
1476 }
1477 }
1478
1479 static void
1480 print_method_failure(const inst_t *ip, const char **dcp)
1481 {
1482 char buf[50];
1483 int stat = ip->start_method_waitstatus;
1484
1485 if (stat != 0) {
1486 if (WIFEXITED(stat)) {
1487 if (WEXITSTATUS(stat) == SMF_EXIT_ERR_CONFIG) {
1488 (void) strlcpy(buf, gettext(
1489 "exited with $SMF_EXIT_ERR_CONFIG"),
1490 sizeof (buf));
1491 } else if (WEXITSTATUS(stat) == SMF_EXIT_ERR_FATAL) {
1492 (void) strlcpy(buf, gettext(
1493 "exited with $SMF_EXIT_ERR_FATAL"),
1494 sizeof (buf));
1495 } else if (WEXITSTATUS(stat) == SMF_EXIT_MON_DEGRADE) {
1496 (void) strlcpy(buf, gettext(
1497 "exited with $SMF_EXIT_MON_DEGRADE"),
1498 sizeof (buf));
1499 } else {
1500 (void) snprintf(buf, sizeof (buf),
1501 gettext("exited with status %d"),
1502 WEXITSTATUS(stat));
1503 }
1504 } else if (WIFSIGNALED(stat)) {
1505 if (WCOREDUMP(stat)) {
1506 if (strsignal(WTERMSIG(stat)) != NULL)
1507 (void) snprintf(buf, sizeof (buf),
1508 gettext("dumped core on %s (%d)"),
1509 strsignal(WTERMSIG(stat)),
1510 WTERMSIG(stat));
1511 else
1512 (void) snprintf(buf, sizeof (buf),
1513 gettext("dumped core signal %d"),
1514 WTERMSIG(stat));
1515 } else {
1516 if (strsignal(WTERMSIG(stat)) != NULL) {
1517 (void) snprintf(buf, sizeof (buf),
1518 gettext("died on %s (%d)"),
1799 }
1800
1801 } else if (strcmp(svcp->state, SCF_STATE_STRING_OFFLINE) == 0) {
1802 if (strcmp(svcp->next_state, SCF_STATE_STRING_ONLINE) == 0) {
1803 (void) puts(gettext(
1804 "Reason: Start method is running."));
1805 dc = DC_STARTING;
1806 } else if (strcmp(svcp->next_state, SCF_STATE_STRING_NONE) ==
1807 0) {
1808 print_dependency_reasons(svcp, verbose);
1809 /* Function prints diagcodes. */
1810 return;
1811 } else {
1812 (void) printf(gettext(
1813 "Reason: Transitioning to state %s.\n"),
1814 svcp->next_state);
1815 dc = DC_TRANSITION;
1816 }
1817
1818 } else if (strcmp(svcp->state, SCF_STATE_STRING_DEGRADED) == 0) {
1819 if (strcmp(svcp->aux_state, "administrative_request") == 0) {
1820 (void) puts(gettext("Reason: Degraded by an "
1821 "administrator."));
1822 dc = DC_ADMINDEGR;
1823 } else if (strcmp(svcp->aux_state, "service_request") == 0) {
1824 if (svcp->aux_fmri) {
1825 (void) printf(gettext("Reason: Degraded by "
1826 "\"%s\"\n"), svcp->aux_fmri);
1827 print_aux_fmri_logs(svcp->aux_fmri);
1828 } else {
1829 (void) puts(gettext("Reason: Degraded by "
1830 "another service."));
1831 }
1832 } else if (strcmp(svcp->aux_state, "method_failed") == 0) {
1833 print_method_failure(svcp, &dc);
1834 } else {
1835 (void) puts(gettext("Reason: Unknown."));
1836 dc = DC_UNKNOWN;
1837 }
1838
1839 } else {
1840 (void) printf(gettext("Reason: Not in valid state (%s).\n"),
1841 svcp->state);
1842 dc = DC_INVALIDSTATE;
1843 }
1844
1845 diagcode:
1846 if (g_msgbase != NULL && dc != NULL)
1847 (void) printf(gettext(" See: %s%s\n"), g_msgbase, dc);
1848 }
1849
1850 static void
1851 print_manpage(int verbose)
1852 {
1853 static char *title = NULL;
1854 static char *section = NULL;
1855
1856 if (title == NULL) {
1857 title = safe_malloc(g_value_sz);
1858 section = safe_malloc(g_value_sz);
1859 }
1860
1861 if (pg_get_single_val(g_pg, SCF_PROPERTY_TM_TITLE, SCF_TYPE_ASTRING,
1862 (void *)title, g_value_sz, 0) != 0)
1863 return;
1864
1865 if (pg_get_single_val(g_pg, SCF_PROPERTY_TM_SECTION,
1866 SCF_TYPE_ASTRING, (void *)section, g_value_sz, 0) != 0)
|