Print this page
NEX-3510 Want "scripted" mode for svcs(1) (fix trailing tab)
NEX-3510 Want "scripted" mode for svcs(1)
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Reviewed by: Hans Rosenfeld <hans.rosenfeld@nexenta.com>


   5  * Common Development and Distribution License (the "License").
   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 (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright (c) 2011, Joyent, Inc. All rights reserved.

  25  * Copyright (c) 2015, 2016 by Delphix. All rights reserved.
  26  */
  27 
  28 /*
  29  * svcs - display attributes of service instances
  30  *
  31  * We have two output formats and six instance selection mechanisms.  The
  32  * primary output format is a line of attributes (selected by -o), possibly
  33  * followed by process description lines (if -p is specified), for each
  34  * instance selected.  The columns available to display are described by the
  35  * struct column columns array.  The columns to actually display are kept in
  36  * the opt_columns array as indicies into the columns array.  The selection
  37  * mechanisms available for this format are service FMRIs (selects all child
  38  * instances), instance FMRIs, instance FMRI glob patterns, instances with
  39  * a certain restarter (-R), dependencies of instances (-d), and dependents of
  40  * instances (-D).  Since the lines must be sorted (per -sS), we'll just stick
  41  * each into a data structure and print them in order when we're done.  To
  42  * avoid listing the same instance twice (when -d and -D aren't given), we'll
  43  * use a hash table of FMRIs to record that we've listed (added to the tree)
  44  * an instance.


 129 ssize_t max_scf_value_length;
 130 ssize_t max_scf_fmri_length;
 131 static ssize_t max_scf_type_length;
 132 static time_t now;
 133 static struct pfmri_list *restarters = NULL;
 134 static int first_paragraph = 1;         /* For -l mode. */
 135 static char *common_name_buf;           /* Sized for maximal length value. */
 136 char *locale;                           /* Current locale. */
 137 char *g_zonename;                       /* zone being operated upon */
 138 
 139 /*
 140  * Pathname storage for path generated from the fmri.
 141  * Used for reading the ctid and (start) pid files for an inetd service.
 142  */
 143 static char genfmri_filename[MAXPATHLEN] = "";
 144 
 145 /* Options */
 146 static int *opt_columns = NULL;         /* Indices into columns to display. */
 147 static int opt_cnum = 0;
 148 static int opt_processes = 0;           /* Print processes? */

 149 static int *opt_sort = NULL;            /* Indices into columns to sort. */
 150 static int opt_snum = 0;
 151 static int opt_nstate_shown = 0;        /* Will nstate be shown? */
 152 static int opt_verbose = 0;
 153 static char *opt_zone;                  /* zone selected, if any */
 154 
 155 /* Minimize string constants. */
 156 static const char * const scf_property_state = SCF_PROPERTY_STATE;
 157 static const char * const scf_property_next_state = SCF_PROPERTY_NEXT_STATE;
 158 static const char * const scf_property_contract = SCF_PROPERTY_CONTRACT;
 159 
 160 
 161 /*
 162  * Utility functions
 163  */
 164 
 165 /*
 166  * For unexpected libscf errors.  The ending newline is necessary to keep
 167  * uu_die() from appending the errno error.
 168  */


 984 
 985         /*
 986          * This function should write sortkey_width bytes into buf which will
 987          * cause memcmp() to sort it properly.  (Unlike sprint() above,
 988          * however, an extra null byte may overrun the buffer.)  The second
 989          * argument controls whether the results are sorted in forward or
 990          * reverse order.
 991          */
 992         void (*get_sortkey)(char *, int, scf_walkinfo_t *);
 993 };
 994 
 995 static void
 996 reverse_bytes(char *buf, size_t len)
 997 {
 998         int i;
 999 
1000         for (i = 0; i < len; ++i)
1001                 buf[i] = ~buf[i];
1002 }
1003 



























1004 /* CTID */
1005 #define CTID_COLUMN_WIDTH               6
1006 #define CTID_COLUMN_BUFSIZE             20      /* max ctid_t + space + \0 */
1007 
1008 static void
1009 sprint_ctid(char **buf, scf_walkinfo_t *wip)
1010 {
1011         int r;
1012         uint64_t c;
1013         size_t newsize = (*buf ? strlen(*buf) : 0) + CTID_COLUMN_BUFSIZE;
1014         char *newbuf = safe_malloc(newsize);
1015         int restarter_spec;
1016 
1017         /*
1018          * Use the restarter specific get pids routine, if available.
1019          * Only check for non-legacy services (wip->pg == 0).
1020          */
1021         if (wip->pg != NULL) {
1022                 r = pg_get_single_val(wip->pg, scf_property_contract,
1023                     SCF_TYPE_COUNT, &c, 0, EMPTY_OK | MULTI_OK);
1024         } else {
1025                 r = ctids_by_restarter(wip, &c, 0, MULTI_OK, &restarter_spec,
1026                     NULL, NULL);
1027                 if (restarter_spec == 0) {
1028                         /* No restarter specific routine */
1029                         r = get_restarter_count_prop(wip->inst,
1030                             scf_property_contract, &c, EMPTY_OK | MULTI_OK);
1031                 }
1032         }
1033 
1034         if (r == 0)
1035                 (void) snprintf(newbuf, newsize, "%s%*lu ",
1036                     *buf ? *buf : "", CTID_COLUMN_WIDTH, (ctid_t)c);
1037         else if (r == E2BIG)
1038                 (void) snprintf(newbuf, newsize, "%s%*lu* ",
1039                     *buf ? *buf : "", CTID_COLUMN_WIDTH - 1, (ctid_t)c);
1040         else
1041                 (void) snprintf(newbuf, newsize, "%s%*s ",
1042                     *buf ? *buf : "", CTID_COLUMN_WIDTH, "-");
1043         if (*buf)
1044                 free(*buf);
1045         *buf = newbuf;
1046 }
1047 
1048 #define CTID_SORTKEY_WIDTH              (sizeof (uint64_t))
1049 
1050 static void
1051 sortkey_ctid(char *buf, int reverse, scf_walkinfo_t *wip)
1052 {
1053         int r;
1054         uint64_t c;
1055         int restarter_spec;
1056 
1057         /*
1058          * Use the restarter specific get pids routine, if available.
1059          * Only check for non-legacy services (wip->pg == 0).
1060          */
1061         if (wip->pg != NULL) {
1062                 r = pg_get_single_val(wip->pg, scf_property_contract,
1063                     SCF_TYPE_COUNT, &c, 0, EMPTY_OK);
1064         } else {
1065                 r = ctids_by_restarter(wip, &c, 0, MULTI_OK, &restarter_spec,


1077                  * work.
1078                  */
1079                 c = BE_64(c);
1080 
1081                 bcopy(&c, buf, CTID_SORTKEY_WIDTH);
1082         } else {
1083                 bzero(buf, CTID_SORTKEY_WIDTH);
1084         }
1085 
1086         if (reverse)
1087                 reverse_bytes(buf, CTID_SORTKEY_WIDTH);
1088 }
1089 
1090 /* DESC */
1091 #define DESC_COLUMN_WIDTH       100
1092 
1093 static void
1094 sprint_desc(char **buf, scf_walkinfo_t *wip)
1095 {
1096         char *x;
1097         size_t newsize;
1098         char *newbuf;
1099 
1100         if (common_name_buf == NULL)
1101                 common_name_buf = safe_malloc(max_scf_value_length + 1);
1102 
1103         bzero(common_name_buf, max_scf_value_length + 1);
1104 
1105         if (wip->pg != NULL) {
1106                 common_name_buf[0] = '-';
1107         } else if (inst_get_single_val(wip->inst, SCF_PG_TM_COMMON_NAME, locale,
1108             SCF_TYPE_USTRING, common_name_buf, max_scf_value_length, 0,
1109             1, 1) == -1 &&
1110             inst_get_single_val(wip->inst, SCF_PG_TM_COMMON_NAME, "C",
1111             SCF_TYPE_USTRING, common_name_buf, max_scf_value_length, 0,
1112             1, 1) == -1) {
1113                 common_name_buf[0] = '-';
1114         }
1115 
1116         /*
1117          * Collapse multi-line tm_common_name values into a single line.
1118          */
1119         for (x = common_name_buf; *x != '\0'; x++)
1120                 if (*x == '\n')
1121                         *x = ' ';
1122 
1123         if (strlen(common_name_buf) > DESC_COLUMN_WIDTH)
1124                 newsize = (*buf ? strlen(*buf) : 0) +
1125                     strlen(common_name_buf) + 1;
1126         else
1127                 newsize = (*buf ? strlen(*buf) : 0) + DESC_COLUMN_WIDTH + 1;
1128         newbuf = safe_malloc(newsize);
1129         (void) snprintf(newbuf, newsize, "%s%-*s ", *buf ? *buf : "",
1130             DESC_COLUMN_WIDTH, common_name_buf);
1131         if (*buf)
1132                 free(*buf);
1133         *buf = newbuf;
1134 }
1135 
1136 /* ARGSUSED */
1137 static void
1138 sortkey_desc(char *buf, int reverse, scf_walkinfo_t *wip)
1139 {
1140         bzero(buf, DESC_COLUMN_WIDTH);
1141 }
1142 
1143 /* State columns (STATE, NSTATE, S, N, SN, STA, NSTA) */
1144 
1145 static char
1146 state_to_char(const char *state)
1147 {
1148         if (strcmp(state, SCF_STATE_STRING_UNINIT) == 0)
1149                 return ('u');
1150 
1151         if (strcmp(state, SCF_STATE_STRING_OFFLINE) == 0)
1152                 return ('0');
1153 


1203                         *buf = 4;
1204                 else if (strcmp(state_name, SCF_STATE_STRING_MAINT) == 0)
1205                         *buf = 5;
1206                 else if (strcmp(state_name, SCF_STATE_STRING_DISABLED) == 0)
1207                         *buf = 1;
1208                 else if (strcmp(state_name, SCF_STATE_STRING_UNINIT) == 0)
1209                         *buf = 6;
1210                 else
1211                         *buf = 7;
1212         } else
1213                 *buf = 0;
1214 
1215         if (reverse)
1216                 *buf = 255 - *buf;
1217 }
1218 
1219 static void
1220 sprint_state(char **buf, scf_walkinfo_t *wip)
1221 {
1222         char state_name[MAX_SCF_STATE_STRING_SZ + 1];
1223         size_t newsize;
1224         char *newbuf;
1225 
1226         if (wip->pg == NULL) {
1227                 get_restarter_string_prop(wip->inst, scf_property_state,
1228                     state_name, sizeof (state_name));
1229 
1230                 /* Don't print blank fields, to ease parsing. */
1231                 if (state_name[0] == '\0') {
1232                         state_name[0] = '-';
1233                         state_name[1] = '\0';
1234                 }
1235 
1236                 if (!opt_nstate_shown && transitioning(wip->inst)) {
1237                         /* Append an asterisk if nstate is valid. */
1238                         (void) strcat(state_name, "*");
1239                 }
1240         } else
1241                 (void) strcpy(state_name, SCF_STATE_STRING_LEGACY);
1242 
1243         newsize = (*buf ? strlen(*buf) : 0) + MAX_SCF_STATE_STRING_SZ + 2;
1244         newbuf = safe_malloc(newsize);
1245         (void) snprintf(newbuf, newsize, "%s%-*s ", *buf ? *buf : "",
1246             MAX_SCF_STATE_STRING_SZ + 1, state_name);
1247 
1248         if (*buf)
1249                 free(*buf);
1250         *buf = newbuf;
1251 }
1252 
1253 static void
1254 sortkey_state(char *buf, int reverse, scf_walkinfo_t *wip)
1255 {
1256         sortkey_states(scf_property_state, buf, reverse, wip);
1257 }
1258 
1259 static void
1260 sprint_nstate(char **buf, scf_walkinfo_t *wip)
1261 {
1262         char next_state_name[MAX_SCF_STATE_STRING_SZ];
1263         boolean_t blank = 0;
1264         size_t newsize;
1265         char *newbuf;
1266 
1267         if (wip->pg == NULL) {
1268                 get_restarter_string_prop(wip->inst, scf_property_next_state,
1269                     next_state_name, sizeof (next_state_name));
1270 
1271                 /* Don't print blank fields, to ease parsing. */
1272                 if (next_state_name[0] == '\0' ||
1273                     strcmp(next_state_name, SCF_STATE_STRING_NONE) == 0)
1274                         blank = 1;
1275         } else
1276                 blank = 1;

1277 
1278         if (blank) {
1279                 next_state_name[0] = '-';
1280                 next_state_name[1] = '\0';
1281         }
1282 
1283         newsize = (*buf ? strlen(*buf) : 0) + MAX_SCF_STATE_STRING_SZ + 1;
1284         newbuf = safe_malloc(newsize);
1285         (void) snprintf(newbuf, newsize, "%s%-*s ", *buf ? *buf : "",
1286             MAX_SCF_STATE_STRING_SZ - 1, next_state_name);
1287         if (*buf)
1288                 free(*buf);
1289         *buf = newbuf;
1290 }
1291 
1292 static void
1293 sortkey_nstate(char *buf, int reverse, scf_walkinfo_t *wip)
1294 {
1295         sortkey_states(scf_property_next_state, buf, reverse, wip);
1296 }
1297 
1298 static void
1299 sprint_s(char **buf, scf_walkinfo_t *wip)
1300 {
1301         char tmp[3];
1302         char state_name[MAX_SCF_STATE_STRING_SZ];
1303         size_t newsize = (*buf ? strlen(*buf) : 0) + 4;
1304         char *newbuf = safe_malloc(newsize);
1305 
1306         if (wip->pg == NULL) {
1307                 get_restarter_string_prop(wip->inst, scf_property_state,
1308                     state_name, sizeof (state_name));
1309                 tmp[0] = state_to_char(state_name);
1310 
1311                 if (!opt_nstate_shown && transitioning(wip->inst))
1312                         tmp[1] = '*';
1313                 else
1314                         tmp[1] = ' ';
1315         } else {
1316                 tmp[0] = 'L';
1317                 tmp[1] = ' ';
1318         }
1319         tmp[2] = ' ';
1320         (void) snprintf(newbuf, newsize, "%s%-*s", *buf ? *buf : "",
1321             3, tmp);
1322         if (*buf)
1323                 free(*buf);
1324         *buf = newbuf;
1325 }
1326 
1327 static void
1328 sprint_n(char **buf, scf_walkinfo_t *wip)
1329 {
1330         char tmp[2];
1331         size_t newsize = (*buf ? strlen(*buf) : 0) + 3;
1332         char *newbuf = safe_malloc(newsize);
1333         char nstate_name[MAX_SCF_STATE_STRING_SZ];
1334 
1335         if (wip->pg == NULL) {
1336                 get_restarter_string_prop(wip->inst, scf_property_next_state,
1337                     nstate_name, sizeof (nstate_name));
1338 
1339                 if (strcmp(nstate_name, SCF_STATE_STRING_NONE) == 0)
1340                         tmp[0] = '-';
1341                 else
1342                         tmp[0] = state_to_char(nstate_name);
1343         } else
1344                 tmp[0] = '-';

1345 
1346         (void) snprintf(newbuf, newsize, "%s%-*s ", *buf ? *buf : "",
1347             2, tmp);
1348         if (*buf)
1349                 free(*buf);
1350         *buf = newbuf;
1351 }
1352 
1353 static void
1354 sprint_sn(char **buf, scf_walkinfo_t *wip)
1355 {
1356         char tmp[3];
1357         size_t newsize = (*buf ? strlen(*buf) : 0) + 4;
1358         char *newbuf = safe_malloc(newsize);
1359         char nstate_name[MAX_SCF_STATE_STRING_SZ];
1360         char state_name[MAX_SCF_STATE_STRING_SZ];
1361 
1362         if (wip->pg == NULL) {
1363                 get_restarter_string_prop(wip->inst, scf_property_state,
1364                     state_name, sizeof (state_name));
1365                 get_restarter_string_prop(wip->inst, scf_property_next_state,
1366                     nstate_name, sizeof (nstate_name));
1367                 tmp[0] = state_to_char(state_name);
1368 
1369                 if (strcmp(nstate_name, SCF_STATE_STRING_NONE) == 0)
1370                         tmp[1] = '-';
1371                 else
1372                         tmp[1] = state_to_char(nstate_name);
1373         } else {
1374                 tmp[0] = 'L';
1375                 tmp[1] = '-';
1376         }
1377 
1378         tmp[2] = ' ';
1379         (void) snprintf(newbuf, newsize, "%s%-*s ", *buf ? *buf : "",
1380             3, tmp);
1381         if (*buf)
1382                 free(*buf);
1383         *buf = newbuf;
1384 }
1385 
1386 /* ARGSUSED */
1387 static void
1388 sortkey_sn(char *buf, int reverse, scf_walkinfo_t *wip)
1389 {
1390         sortkey_state(buf, reverse, wip);
1391         sortkey_nstate(buf + 1, reverse, wip);
1392 }
1393 
1394 static const char *
1395 state_abbrev(const char *state)
1396 {
1397         if (strcmp(state, SCF_STATE_STRING_UNINIT) == 0)
1398                 return ("UN");
1399         if (strcmp(state, SCF_STATE_STRING_OFFLINE) == 0)
1400                 return ("OFF");
1401         if (strcmp(state, SCF_STATE_STRING_ONLINE) == 0)
1402                 return ("ON");
1403         if (strcmp(state, SCF_STATE_STRING_MAINT) == 0)
1404                 return ("MNT");
1405         if (strcmp(state, SCF_STATE_STRING_DISABLED) == 0)
1406                 return ("DIS");
1407         if (strcmp(state, SCF_STATE_STRING_DEGRADED) == 0)
1408                 return ("DGD");
1409         if (strcmp(state, SCF_STATE_STRING_LEGACY) == 0)
1410                 return ("LRC");
1411 
1412         return ("?");
1413 }
1414 
1415 static void
1416 sprint_sta(char **buf, scf_walkinfo_t *wip)
1417 {
1418         char state_name[MAX_SCF_STATE_STRING_SZ];
1419         char sta[5];
1420         size_t newsize = (*buf ? strlen(*buf) : 0) + 6;
1421         char *newbuf = safe_malloc(newsize);
1422 
1423         if (wip->pg == NULL)
1424                 get_restarter_string_prop(wip->inst, scf_property_state,
1425                     state_name, sizeof (state_name));
1426         else
1427                 (void) strcpy(state_name, SCF_STATE_STRING_LEGACY);

1428 
1429         (void) strcpy(sta, state_abbrev(state_name));
1430 
1431         if (wip->pg == NULL && !opt_nstate_shown && transitioning(wip->inst))
1432                 (void) strcat(sta, "*");
1433 
1434         (void) snprintf(newbuf, newsize, "%s%-4s ", *buf ? *buf : "", sta);
1435         if (*buf)
1436                 free(*buf);
1437         *buf = newbuf;
1438 }
1439 
1440 static void
1441 sprint_nsta(char **buf, scf_walkinfo_t *wip)
1442 {
1443         char state_name[MAX_SCF_STATE_STRING_SZ];
1444         size_t newsize = (*buf ? strlen(*buf) : 0) + 6;
1445         char *newbuf = safe_malloc(newsize);
1446 
1447         if (wip->pg == NULL)
1448                 get_restarter_string_prop(wip->inst, scf_property_next_state,
1449                     state_name, sizeof (state_name));
1450         else
1451                 (void) strcpy(state_name, SCF_STATE_STRING_NONE);

1452 
1453         if (strcmp(state_name, SCF_STATE_STRING_NONE) == 0)
1454                 (void) snprintf(newbuf, newsize, "%s%-4s ", *buf ? *buf : "",
1455                     "-");
1456         else
1457                 (void) snprintf(newbuf, newsize, "%s%-4s ", *buf ? *buf : "",
1458                     state_abbrev(state_name));
1459         if (*buf)
1460                 free(*buf);
1461         *buf = newbuf;
1462 }
1463 
1464 /* FMRI */
1465 #define FMRI_COLUMN_WIDTH       50
1466 static void
1467 sprint_fmri(char **buf, scf_walkinfo_t *wip)
1468 {
1469         char *fmri_buf = safe_malloc(max_scf_fmri_length + 1);
1470         size_t newsize;
1471         char *newbuf;
1472 
1473         if (wip->pg == NULL) {
1474                 if (scf_instance_to_fmri(wip->inst, fmri_buf,
1475                     max_scf_fmri_length + 1) == -1)
1476                         scfdie();
1477         } else {
1478                 (void) strcpy(fmri_buf, SCF_FMRI_LEGACY_PREFIX);
1479                 if (pg_get_single_val(wip->pg, SCF_LEGACY_PROPERTY_NAME,
1480                     SCF_TYPE_ASTRING, fmri_buf +
1481                     sizeof (SCF_FMRI_LEGACY_PREFIX) - 1,
1482                     max_scf_fmri_length + 1 -
1483                     (sizeof (SCF_FMRI_LEGACY_PREFIX) - 1), 0) != 0)
1484                         (void) strcat(fmri_buf, LEGACY_UNKNOWN);
1485         }
1486 
1487         if (strlen(fmri_buf) > FMRI_COLUMN_WIDTH)
1488                 newsize = (*buf ? strlen(*buf) : 0) + strlen(fmri_buf) + 2;
1489         else
1490                 newsize = (*buf ? strlen(*buf) : 0) + FMRI_COLUMN_WIDTH + 2;
1491         newbuf = safe_malloc(newsize);
1492         (void) snprintf(newbuf, newsize, "%s%-*s ", *buf ? *buf : "",
1493             FMRI_COLUMN_WIDTH, fmri_buf);
1494         free(fmri_buf);
1495         if (*buf)
1496                 free(*buf);
1497         *buf = newbuf;
1498 }
1499 
1500 static void
1501 sortkey_fmri(char *buf, int reverse, scf_walkinfo_t *wip)
1502 {
1503         char *tmp = NULL;
1504 
1505         sprint_fmri(&tmp, wip);
1506         bcopy(tmp, buf, FMRI_COLUMN_WIDTH);
1507         free(tmp);
1508         if (reverse)
1509                 reverse_bytes(buf, FMRI_COLUMN_WIDTH);
1510 }
1511 
1512 /* Component columns */
1513 #define COMPONENT_COLUMN_WIDTH  20
1514 static void
1515 sprint_scope(char **buf, scf_walkinfo_t *wip)
1516 {
1517         char *scope_buf = safe_malloc(max_scf_name_length + 1);
1518         size_t newsize = (*buf ? strlen(*buf) : 0) + COMPONENT_COLUMN_WIDTH + 2;
1519         char *newbuf = safe_malloc(newsize);
1520 
1521         assert(wip->scope != NULL);
1522 
1523         if (scf_scope_get_name(wip->scope, scope_buf, max_scf_name_length) < 0)
1524                 scfdie();
1525 
1526         (void) snprintf(newbuf, newsize, "%s%-*s ", *buf ? *buf : "",
1527             COMPONENT_COLUMN_WIDTH, scope_buf);
1528         if (*buf)
1529                 free(*buf);
1530         *buf = newbuf;
1531         free(scope_buf);
1532 }
1533 
1534 static void
1535 sortkey_scope(char *buf, int reverse, scf_walkinfo_t *wip)
1536 {
1537         char *tmp = NULL;
1538 
1539         sprint_scope(&tmp, wip);
1540         bcopy(tmp, buf, COMPONENT_COLUMN_WIDTH);
1541         free(tmp);
1542         if (reverse)
1543                 reverse_bytes(buf, COMPONENT_COLUMN_WIDTH);
1544 }
1545 
1546 static void
1547 sprint_service(char **buf, scf_walkinfo_t *wip)
1548 {
1549         char *svc_buf = safe_malloc(max_scf_name_length + 1);
1550         char *newbuf;
1551         size_t newsize;
1552 
1553         if (wip->pg == NULL) {
1554                 if (scf_service_get_name(wip->svc, svc_buf,
1555                     max_scf_name_length + 1) < 0)
1556                         scfdie();
1557         } else {
1558                 if (pg_get_single_val(wip->pg, "name", SCF_TYPE_ASTRING,
1559                     svc_buf, max_scf_name_length + 1, EMPTY_OK) != 0)
1560                         (void) strcpy(svc_buf, LEGACY_UNKNOWN);
1561         }
1562 
1563 
1564         if (strlen(svc_buf) > COMPONENT_COLUMN_WIDTH)
1565                 newsize = (*buf ? strlen(*buf) : 0) + strlen(svc_buf) + 2;
1566         else
1567                 newsize = (*buf ? strlen(*buf) : 0) +
1568                     COMPONENT_COLUMN_WIDTH + 2;
1569         newbuf = safe_malloc(newsize);
1570         (void) snprintf(newbuf, newsize, "%s%-*s ", *buf ? *buf : "",
1571             COMPONENT_COLUMN_WIDTH, svc_buf);
1572         free(svc_buf);
1573         if (*buf)
1574                 free(*buf);
1575         *buf = newbuf;
1576 }
1577 
1578 static void
1579 sortkey_service(char *buf, int reverse, scf_walkinfo_t *wip)
1580 {
1581         char *tmp = NULL;
1582 
1583         sprint_service(&tmp, wip);
1584         bcopy(tmp, buf, COMPONENT_COLUMN_WIDTH);
1585         free(tmp);
1586         if (reverse)
1587                 reverse_bytes(buf, COMPONENT_COLUMN_WIDTH);
1588 }
1589 
1590 /* INST */
1591 static void
1592 sprint_instance(char **buf, scf_walkinfo_t *wip)
1593 {
1594         char *tmp = safe_malloc(max_scf_name_length + 1);
1595         size_t newsize = (*buf ? strlen(*buf) : 0) + COMPONENT_COLUMN_WIDTH + 2;
1596         char *newbuf = safe_malloc(newsize);
1597 
1598         if (wip->pg == NULL) {
1599                 if (scf_instance_get_name(wip->inst, tmp,
1600                     max_scf_name_length + 1) < 0)
1601                         scfdie();
1602         } else {
1603                 tmp[0] = '-';
1604                 tmp[1] = '\0';
1605         }
1606 
1607         (void) snprintf(newbuf, newsize, "%s%-*s ", *buf ? *buf : "",
1608             COMPONENT_COLUMN_WIDTH, tmp);
1609         if (*buf)
1610                 free(*buf);
1611         *buf = newbuf;
1612         free(tmp);
1613 }
1614 
1615 static void
1616 sortkey_instance(char *buf, int reverse, scf_walkinfo_t *wip)
1617 {
1618         char *tmp = NULL;
1619 
1620         sprint_instance(&tmp, wip);
1621         bcopy(tmp, buf, COMPONENT_COLUMN_WIDTH);
1622         free(tmp);
1623         if (reverse)
1624                 reverse_bytes(buf, COMPONENT_COLUMN_WIDTH);
1625 }
1626 
1627 /* STIME */
1628 #define STIME_COLUMN_WIDTH              8
1629 #define FORMAT_TIME                     "%k:%M:%S"
1630 #define FORMAT_DATE                     "%b_%d  "
1631 #define FORMAT_YEAR                     "%Y    "
1632 
1633 /*
1634  * sprint_stime() will allocate a new buffer and snprintf the services's
1635  * state timestamp.  If the timestamp is unavailable for some reason
1636  * a '-' is given instead.
1637  */
1638 static void
1639 sprint_stime(char **buf, scf_walkinfo_t *wip)
1640 {
1641         int r;
1642         struct timeval tv;
1643         time_t then;
1644         struct tm *tm;
1645         char st_buf[STIME_COLUMN_WIDTH + 1];
1646         size_t newsize = (*buf ? strlen(*buf) : 0) + STIME_COLUMN_WIDTH + 2;
1647         char *newbuf = safe_malloc(newsize);
1648 
1649         if (wip->pg == NULL) {
1650                 r = get_restarter_time_prop(wip->inst,
1651                     SCF_PROPERTY_STATE_TIMESTAMP, &tv, 0);
1652         } else {
1653                 r = pg_get_single_val(wip->pg, SCF_PROPERTY_STATE_TIMESTAMP,
1654                     SCF_TYPE_TIME, &tv, NULL, 0);
1655         }
1656 
1657         if (r != 0) {
1658                 /*
1659                  * There's something amiss with our service
1660                  * so we'll print a '-' for STIME.
1661                  */
1662                 (void) snprintf(newbuf, newsize, "%s%-*s", *buf ? *buf : "",
1663                     STIME_COLUMN_WIDTH + 1, "-");
1664         } else {
1665                 /* tv should be valid so we'll format it */
1666                 then = (time_t)tv.tv_sec;
1667 
1668                 tm = localtime(&then);
1669                 /*
1670                  * Print time if started within the past 24 hours, print date
1671                  * if within the past 12 months or, finally, print year if
1672                  * started greater than 12 months ago.
1673                  */
1674                 if (now - then < 24 * 60 * 60) {
1675                         (void) strftime(st_buf, sizeof (st_buf),
1676                             gettext(FORMAT_TIME), tm);
1677                 } else if (now - then < 12 * 30 * 24 * 60 * 60) {
1678                         (void) strftime(st_buf, sizeof (st_buf),
1679                             gettext(FORMAT_DATE), tm);
1680                 } else {
1681                         (void) strftime(st_buf, sizeof (st_buf),
1682                             gettext(FORMAT_YEAR), tm);
1683                 }
1684                 (void) snprintf(newbuf, newsize, "%s%-*s ", *buf ? *buf : "",
1685                     STIME_COLUMN_WIDTH + 1, st_buf);
1686         }
1687         if (*buf)
1688                 free(*buf);
1689         *buf = newbuf;
1690 }
1691 
1692 #define STIME_SORTKEY_WIDTH             (sizeof (uint64_t) + sizeof (uint32_t))
1693 
1694 /* ARGSUSED */
1695 static void
1696 sortkey_stime(char *buf, int reverse, scf_walkinfo_t *wip)
1697 {
1698         struct timeval tv;
1699         int r;
1700 
1701         if (wip->pg == NULL)
1702                 r = get_restarter_time_prop(wip->inst,
1703                     SCF_PROPERTY_STATE_TIMESTAMP, &tv, 0);
1704         else
1705                 r = pg_get_single_val(wip->pg, SCF_PROPERTY_STATE_TIMESTAMP,
1706                     SCF_TYPE_TIME, &tv, NULL, 0);
1707 
1708         if (r == 0) {
1709                 int64_t sec;


1714                 us = tv.tv_usec;
1715 
1716                 sec = BE_64(sec);
1717                 us = BE_32(us);
1718                 bcopy(&sec, buf, sizeof (sec));
1719                 bcopy(&us, buf + sizeof (sec), sizeof (us));
1720         } else {
1721                 bzero(buf, STIME_SORTKEY_WIDTH);
1722         }
1723 
1724         if (reverse)
1725                 reverse_bytes(buf, STIME_SORTKEY_WIDTH);
1726 }
1727 
1728 /* ZONE */
1729 #define ZONE_COLUMN_WIDTH       16
1730 /*ARGSUSED*/
1731 static void
1732 sprint_zone(char **buf, scf_walkinfo_t *wip)
1733 {
1734         size_t newsize;
1735         char *newbuf, *zonename = g_zonename, b[ZONENAME_MAX];
1736 
1737         if (zonename == NULL) {
1738                 zoneid_t zoneid = getzoneid();
1739 
1740                 if (getzonenamebyid(zoneid, b, sizeof (b)) < 0)
1741                         uu_die(gettext("could not determine zone name"));
1742 
1743                 zonename = b;
1744         }
1745 
1746         if (strlen(zonename) > ZONE_COLUMN_WIDTH)
1747                 newsize = (*buf ? strlen(*buf) : 0) + strlen(zonename) + 2;
1748         else
1749                 newsize = (*buf ? strlen(*buf) : 0) + ZONE_COLUMN_WIDTH + 2;
1750 
1751         newbuf = safe_malloc(newsize);
1752         (void) snprintf(newbuf, newsize, "%s%-*s ", *buf ? *buf : "",
1753             ZONE_COLUMN_WIDTH, zonename);
1754 
1755         if (*buf)
1756                 free(*buf);
1757         *buf = newbuf;
1758 }
1759 
1760 static void
1761 sortkey_zone(char *buf, int reverse, scf_walkinfo_t *wip)
1762 {
1763         char *tmp = NULL;
1764 
1765         sprint_zone(&tmp, wip);
1766         bcopy(tmp, buf, ZONE_COLUMN_WIDTH);
1767         free(tmp);
1768         if (reverse)
1769                 reverse_bytes(buf, ZONE_COLUMN_WIDTH);
1770 }
1771 
1772 /*
1773  * Information about columns which can be displayed.  If you add something,
1774  * check MAX_COLUMN_NAME_LENGTH_STR & update description_of_column() below.
1775  */
1776 static const struct column columns[] = {
1777         { "CTID", CTID_COLUMN_WIDTH, sprint_ctid,
1778                 CTID_SORTKEY_WIDTH, sortkey_ctid },
1779         { "DESC", DESC_COLUMN_WIDTH, sprint_desc,
1780                 DESC_COLUMN_WIDTH, sortkey_desc },
1781         { "FMRI", FMRI_COLUMN_WIDTH, sprint_fmri,
1782                 FMRI_COLUMN_WIDTH, sortkey_fmri },
1783         { "INST", COMPONENT_COLUMN_WIDTH, sprint_instance,
1784                 COMPONENT_COLUMN_WIDTH, sortkey_instance },
1785         { "N", 1,  sprint_n, 1, sortkey_nstate },
1786         { "NSTA", 4, sprint_nsta, 1, sortkey_nstate },
1787         { "NSTATE", MAX_SCF_STATE_STRING_SZ - 1, sprint_nstate,
1788                 1, sortkey_nstate },
1789         { "S", 2, sprint_s, 1, sortkey_state },
1790         { "SCOPE", COMPONENT_COLUMN_WIDTH, sprint_scope,
1791                 COMPONENT_COLUMN_WIDTH, sortkey_scope },
1792         { "SN", 2, sprint_sn, 2, sortkey_sn },
1793         { "SVC", COMPONENT_COLUMN_WIDTH, sprint_service,
1794                 COMPONENT_COLUMN_WIDTH, sortkey_service },
1795         { "STA", 4, sprint_sta, 1, sortkey_state },
1796         { "STATE", MAX_SCF_STATE_STRING_SZ - 1 + 1, sprint_state,
1797                 1, sortkey_state },
1798         { "STIME", STIME_COLUMN_WIDTH, sprint_stime,
1799                 STIME_SORTKEY_WIDTH, sortkey_stime },
1800         { "ZONE", ZONE_COLUMN_WIDTH, sprint_zone,
1801                 ZONE_COLUMN_WIDTH, sortkey_zone },
1802 };
1803 
1804 #define MAX_COLUMN_NAME_LENGTH_STR      "6"
1805 
1806 static const int ncolumns = sizeof (columns) / sizeof (columns[0]);
1807 
1808 /*
1809  * Necessary thanks to gettext() & xgettext.
1810  */
1811 static const char *
1812 description_of_column(int c)
1813 {
1814         const char *s = NULL;
1815 
1816         switch (c) {


1852                 break;
1853         case 12:
1854                 s = gettext("name for current state");
1855                 break;
1856         case 13:
1857                 s = gettext("time of last state change");
1858                 break;
1859         case 14:
1860                 s = gettext("name of zone");
1861                 break;
1862         }
1863 
1864         assert(s != NULL);
1865         return (s);
1866 }
1867 
1868 
1869 static void
1870 print_usage(const char *progname, FILE *f, boolean_t do_exit)
1871 {
1872         (void) fprintf(f, gettext(
1873             "Usage: %1$s [-aHpv] [-o col[,col ... ]] [-R restarter] "
1874             "[-sS col] [-Z | -z zone ]\n            [<service> ...]\n"
1875             "       %1$s -d | -D [-Hpv] [-o col[,col ... ]] [-sS col] "
1876             "[-Z | -z zone ]\n            [<service> ...]\n"
1877             "       %1$s [-l | -L] [-Z | -z zone] <service> ...\n"
1878             "       %1$s -x [-v] [-Z | -z zone] [<service> ...]\n"
1879             "       %1$s -?\n"), progname);
1880 
1881         if (do_exit)
1882                 exit(UU_EXIT_USAGE);
1883 }
1884 
1885 #define argserr(progname)       print_usage(progname, stderr, B_TRUE)
1886 
1887 static void
1888 print_help(const char *progname)
1889 {
1890         int i;
1891 
1892         print_usage(progname, stdout, B_FALSE);
1893 
1894         (void) printf(gettext("\n"
1895         "\t-a  list all service instances rather than "
1896         "only those that are enabled\n"
1897         "\t-d  list dependencies of the specified service(s)\n"
1898         "\t-D  list dependents of the specified service(s)\n"
1899         "\t-H  omit header line from output\n"


3437 /* ARGSUSED */
3438 static void
3439 errignore(const char *str, ...)
3440 {}
3441 
3442 int
3443 main(int argc, char **argv)
3444 {
3445         char opt, opt_mode;
3446         int i, n;
3447         char *columns_str = NULL;
3448         char *cp;
3449         const char *progname;
3450         int err, missing = 1, ignored, *errarg;
3451         uint_t nzents = 0, zent = 0;
3452         zoneid_t *zids = NULL;
3453         char zonename[ZONENAME_MAX];
3454         void (*errfunc)(const char *, ...);
3455 
3456         int show_all = 0;
3457         int show_header = 1;
3458         int show_zones = 0;
3459 
3460         const char * const options = "aHpvno:R:s:S:dDlL?xZz:";
3461 
3462         (void) setlocale(LC_ALL, "");
3463 
3464         locale = setlocale(LC_MESSAGES, NULL);
3465         if (locale) {
3466                 locale = safe_strdup(locale);
3467                 _scf_sanitize_locale(locale);
3468         }
3469 
3470         (void) textdomain(TEXT_DOMAIN);
3471         progname = uu_setpname(argv[0]);
3472 
3473         exit_status = UU_EXIT_OK;
3474 
3475         max_scf_name_length = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH);
3476         max_scf_value_length = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH);
3477         max_scf_fmri_length = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH);


3527 
3528                 default:
3529                         break;
3530                 }
3531         }
3532 
3533         sortkey_sz = 0;
3534 
3535         optind = 1;     /* Reset getopt() */
3536         while ((opt = getopt(argc, argv, options)) != -1) {
3537                 switch (opt) {
3538                 case 'a':
3539                         if (opt_mode != 0)
3540                                 argserr(progname);
3541                         show_all = 1;
3542                         break;
3543 
3544                 case 'H':
3545                         if (opt_mode == 'l' || opt_mode == 'x')
3546                                 argserr(progname);
3547                         show_header = 0;
3548                         break;
3549 
3550                 case 'p':
3551                         if (opt_mode == 'x')
3552                                 argserr(progname);
3553                         opt_processes = 1;
3554                         break;
3555 
3556                 case 'v':
3557                         opt_verbose = 1;
3558                         break;
3559 
3560                 case 'o':
3561                         if (opt_mode == 'l' || opt_mode == 'x')
3562                                 argserr(progname);
3563                         columns_str = optarg;
3564                         break;
3565 
3566                 case 'R':
3567                         if (opt_mode != 0 || opt_mode == 'x')


3906         case 'n':
3907                 break;
3908 
3909         default:
3910                 assert(0);
3911                 abort();
3912         }
3913 
3914 nextzone:
3915         if (show_zones && zent < nzents && exit_status == 0) {
3916                 scf_handle_destroy(h);
3917                 goto again;
3918         }
3919 
3920         if (show_zones && exit_status == 0)
3921                 exit_status = missing;
3922 
3923         if (opt_columns == NULL)
3924                 return (exit_status);
3925 
3926         if (show_header)
3927                 print_header();
3928 
3929         (void) uu_avl_walk(lines, print_line, NULL, 0);
3930 
3931         return (exit_status);
3932 }


   5  * Common Development and Distribution License (the "License").
   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 (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright (c) 2011, Joyent, Inc. All rights reserved.
  25  * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
  26  * Copyright (c) 2015, 2016 by Delphix. All rights reserved.
  27  */
  28 
  29 /*
  30  * svcs - display attributes of service instances
  31  *
  32  * We have two output formats and six instance selection mechanisms.  The
  33  * primary output format is a line of attributes (selected by -o), possibly
  34  * followed by process description lines (if -p is specified), for each
  35  * instance selected.  The columns available to display are described by the
  36  * struct column columns array.  The columns to actually display are kept in
  37  * the opt_columns array as indicies into the columns array.  The selection
  38  * mechanisms available for this format are service FMRIs (selects all child
  39  * instances), instance FMRIs, instance FMRI glob patterns, instances with
  40  * a certain restarter (-R), dependencies of instances (-d), and dependents of
  41  * instances (-D).  Since the lines must be sorted (per -sS), we'll just stick
  42  * each into a data structure and print them in order when we're done.  To
  43  * avoid listing the same instance twice (when -d and -D aren't given), we'll
  44  * use a hash table of FMRIs to record that we've listed (added to the tree)
  45  * an instance.


 130 ssize_t max_scf_value_length;
 131 ssize_t max_scf_fmri_length;
 132 static ssize_t max_scf_type_length;
 133 static time_t now;
 134 static struct pfmri_list *restarters = NULL;
 135 static int first_paragraph = 1;         /* For -l mode. */
 136 static char *common_name_buf;           /* Sized for maximal length value. */
 137 char *locale;                           /* Current locale. */
 138 char *g_zonename;                       /* zone being operated upon */
 139 
 140 /*
 141  * Pathname storage for path generated from the fmri.
 142  * Used for reading the ctid and (start) pid files for an inetd service.
 143  */
 144 static char genfmri_filename[MAXPATHLEN] = "";
 145 
 146 /* Options */
 147 static int *opt_columns = NULL;         /* Indices into columns to display. */
 148 static int opt_cnum = 0;
 149 static int opt_processes = 0;           /* Print processes? */
 150 static int opt_scripted = 0;            /* No header, tabs as separators. */
 151 static int *opt_sort = NULL;            /* Indices into columns to sort. */
 152 static int opt_snum = 0;
 153 static int opt_nstate_shown = 0;        /* Will nstate be shown? */
 154 static int opt_verbose = 0;
 155 static char *opt_zone;                  /* zone selected, if any */
 156 
 157 /* Minimize string constants. */
 158 static const char * const scf_property_state = SCF_PROPERTY_STATE;
 159 static const char * const scf_property_next_state = SCF_PROPERTY_NEXT_STATE;
 160 static const char * const scf_property_contract = SCF_PROPERTY_CONTRACT;
 161 
 162 
 163 /*
 164  * Utility functions
 165  */
 166 
 167 /*
 168  * For unexpected libscf errors.  The ending newline is necessary to keep
 169  * uu_die() from appending the errno error.
 170  */


 986 
 987         /*
 988          * This function should write sortkey_width bytes into buf which will
 989          * cause memcmp() to sort it properly.  (Unlike sprint() above,
 990          * however, an extra null byte may overrun the buffer.)  The second
 991          * argument controls whether the results are sorted in forward or
 992          * reverse order.
 993          */
 994         void (*get_sortkey)(char *, int, scf_walkinfo_t *);
 995 };
 996 
 997 static void
 998 reverse_bytes(char *buf, size_t len)
 999 {
1000         int i;
1001 
1002         for (i = 0; i < len; ++i)
1003                 buf[i] = ~buf[i];
1004 }
1005 
1006 static void
1007 sprint_str(char **buf, const char *str, size_t width)
1008 {
1009         char *newbuf;
1010         size_t newsz = (*buf != NULL ? strlen(*buf) : 0) + 2;
1011 
1012         if (opt_scripted)
1013                 newsz += strlen(str);
1014         else
1015                 newsz += width;
1016 
1017         newbuf = safe_malloc(newsz);
1018 
1019         if (opt_scripted) {
1020                 (void) snprintf(newbuf, newsz, "%s%s%s",
1021                     *buf != NULL ? *buf : "",
1022                     *buf != NULL ? "\t" : "",
1023                     str);
1024         } else {
1025                 (void) snprintf(newbuf, newsz, "%s%-*s ",
1026                     *buf != NULL ? *buf : "", width, str);
1027         }
1028 
1029         free(*buf);
1030         *buf = newbuf;
1031 }
1032 
1033 /* CTID */
1034 #define CTID_COLUMN_WIDTH               6
1035 #define CTID_COLUMN_BUFSIZE             20      /* max ctid_t + space + \0 */
1036 
1037 static void
1038 sprint_ctid(char **buf, scf_walkinfo_t *wip)
1039 {
1040         int r;
1041         uint64_t c;
1042         char ctid_buf[CTID_COLUMN_BUFSIZE] = { 0 };
1043         char *cstr;
1044         int restarter_spec;
1045 
1046         /*
1047          * Use the restarter specific get pids routine, if available.
1048          * Only check for non-legacy services (wip->pg == 0).
1049          */
1050         if (wip->pg != NULL) {
1051                 r = pg_get_single_val(wip->pg, scf_property_contract,
1052                     SCF_TYPE_COUNT, &c, 0, EMPTY_OK | MULTI_OK);
1053         } else {
1054                 r = ctids_by_restarter(wip, &c, 0, MULTI_OK, &restarter_spec,
1055                     NULL, NULL);
1056                 if (restarter_spec == 0) {
1057                         /* No restarter specific routine */
1058                         r = get_restarter_count_prop(wip->inst,
1059                             scf_property_contract, &c, EMPTY_OK | MULTI_OK);
1060                 }
1061         }
1062 
1063         if (r == 0 || r == E2BIG) {
1064                 if (r == E2BIG)
1065                         ctid_buf[CTID_COLUMN_BUFSIZE - 2] = '*';
1066                 cstr = ulltostr(c, &ctid_buf[CTID_COLUMN_BUFSIZE - 2]);
1067                 sprint_str(buf, cstr, CTID_COLUMN_WIDTH);
1068         } else {
1069                 sprint_str(buf, "-", CTID_COLUMN_WIDTH);
1070         }




1071 }
1072 
1073 #define CTID_SORTKEY_WIDTH              (sizeof (uint64_t))
1074 
1075 static void
1076 sortkey_ctid(char *buf, int reverse, scf_walkinfo_t *wip)
1077 {
1078         int r;
1079         uint64_t c;
1080         int restarter_spec;
1081 
1082         /*
1083          * Use the restarter specific get pids routine, if available.
1084          * Only check for non-legacy services (wip->pg == 0).
1085          */
1086         if (wip->pg != NULL) {
1087                 r = pg_get_single_val(wip->pg, scf_property_contract,
1088                     SCF_TYPE_COUNT, &c, 0, EMPTY_OK);
1089         } else {
1090                 r = ctids_by_restarter(wip, &c, 0, MULTI_OK, &restarter_spec,


1102                  * work.
1103                  */
1104                 c = BE_64(c);
1105 
1106                 bcopy(&c, buf, CTID_SORTKEY_WIDTH);
1107         } else {
1108                 bzero(buf, CTID_SORTKEY_WIDTH);
1109         }
1110 
1111         if (reverse)
1112                 reverse_bytes(buf, CTID_SORTKEY_WIDTH);
1113 }
1114 
1115 /* DESC */
1116 #define DESC_COLUMN_WIDTH       100
1117 
1118 static void
1119 sprint_desc(char **buf, scf_walkinfo_t *wip)
1120 {
1121         char *x;


1122 
1123         if (common_name_buf == NULL)
1124                 common_name_buf = safe_malloc(max_scf_value_length + 1);
1125 
1126         bzero(common_name_buf, max_scf_value_length + 1);
1127 
1128         if (wip->pg != NULL) {
1129                 common_name_buf[0] = '-';
1130         } else if (inst_get_single_val(wip->inst, SCF_PG_TM_COMMON_NAME, locale,
1131             SCF_TYPE_USTRING, common_name_buf, max_scf_value_length, 0,
1132             1, 1) == -1 &&
1133             inst_get_single_val(wip->inst, SCF_PG_TM_COMMON_NAME, "C",
1134             SCF_TYPE_USTRING, common_name_buf, max_scf_value_length, 0,
1135             1, 1) == -1) {
1136                 common_name_buf[0] = '-';
1137         }
1138 
1139         /*
1140          * Collapse multi-line tm_common_name values into a single line.
1141          */
1142         for (x = common_name_buf; *x != '\0'; x++)
1143                 if (*x == '\n')
1144                         *x = ' ';
1145 
1146         sprint_str(buf, common_name_buf, DESC_COLUMN_WIDTH);










1147 }
1148 
1149 /* ARGSUSED */
1150 static void
1151 sortkey_desc(char *buf, int reverse, scf_walkinfo_t *wip)
1152 {
1153         bzero(buf, DESC_COLUMN_WIDTH);
1154 }
1155 
1156 /* State columns (STATE, NSTATE, S, N, SN, STA, NSTA) */
1157 
1158 static char
1159 state_to_char(const char *state)
1160 {
1161         if (strcmp(state, SCF_STATE_STRING_UNINIT) == 0)
1162                 return ('u');
1163 
1164         if (strcmp(state, SCF_STATE_STRING_OFFLINE) == 0)
1165                 return ('0');
1166 


1216                         *buf = 4;
1217                 else if (strcmp(state_name, SCF_STATE_STRING_MAINT) == 0)
1218                         *buf = 5;
1219                 else if (strcmp(state_name, SCF_STATE_STRING_DISABLED) == 0)
1220                         *buf = 1;
1221                 else if (strcmp(state_name, SCF_STATE_STRING_UNINIT) == 0)
1222                         *buf = 6;
1223                 else
1224                         *buf = 7;
1225         } else
1226                 *buf = 0;
1227 
1228         if (reverse)
1229                 *buf = 255 - *buf;
1230 }
1231 
1232 static void
1233 sprint_state(char **buf, scf_walkinfo_t *wip)
1234 {
1235         char state_name[MAX_SCF_STATE_STRING_SZ + 1];


1236 
1237         if (wip->pg == NULL) {
1238                 get_restarter_string_prop(wip->inst, scf_property_state,
1239                     state_name, sizeof (state_name));
1240 
1241                 /* Don't print blank fields, to ease parsing. */
1242                 if (state_name[0] == '\0') {
1243                         state_name[0] = '-';
1244                         state_name[1] = '\0';
1245                 }
1246 
1247                 if (!opt_nstate_shown && transitioning(wip->inst)) {
1248                         /* Append an asterisk if nstate is valid. */
1249                         (void) strcat(state_name, "*");
1250                 }
1251         } else
1252                 (void) strcpy(state_name, SCF_STATE_STRING_LEGACY);
1253 
1254         sprint_str(buf, state_name, MAX_SCF_STATE_STRING_SZ);







1255 }
1256 
1257 static void
1258 sortkey_state(char *buf, int reverse, scf_walkinfo_t *wip)
1259 {
1260         sortkey_states(scf_property_state, buf, reverse, wip);
1261 }
1262 
1263 static void
1264 sprint_nstate(char **buf, scf_walkinfo_t *wip)
1265 {
1266         char next_state_name[MAX_SCF_STATE_STRING_SZ + 1];
1267         boolean_t blank = 0;


1268 
1269         if (wip->pg == NULL) {
1270                 get_restarter_string_prop(wip->inst, scf_property_next_state,
1271                     next_state_name, sizeof (next_state_name));
1272 
1273                 /* Don't print blank fields, to ease parsing. */
1274                 if (next_state_name[0] == '\0' ||
1275                     strcmp(next_state_name, SCF_STATE_STRING_NONE) == 0)
1276                         blank = 1;
1277         } else {
1278                 blank = 1;
1279         }
1280 
1281         if (blank) {
1282                 next_state_name[0] = '-';
1283                 next_state_name[1] = '\0';
1284         }
1285 
1286         sprint_str(buf, next_state_name, MAX_SCF_STATE_STRING_SZ);






1287 }
1288 
1289 static void
1290 sortkey_nstate(char *buf, int reverse, scf_walkinfo_t *wip)
1291 {
1292         sortkey_states(scf_property_next_state, buf, reverse, wip);
1293 }
1294 
1295 static void
1296 sprint_s(char **buf, scf_walkinfo_t *wip)
1297 {
1298         char state_name[MAX_SCF_STATE_STRING_SZ + 1];
1299         char tmp[3] = { 0 };


1300 
1301         if (wip->pg == NULL) {
1302                 get_restarter_string_prop(wip->inst, scf_property_state,
1303                     state_name, sizeof (state_name));
1304                 tmp[0] = state_to_char(state_name);
1305 
1306                 if (!opt_nstate_shown && transitioning(wip->inst))
1307                         tmp[1] = '*';
1308                 else
1309                         tmp[1] = ' ';
1310         } else {
1311                 tmp[0] = 'L';
1312                 tmp[1] = ' ';
1313         }
1314         tmp[2] = ' ';
1315 
1316         sprint_str(buf, tmp, 2);



1317 }
1318 
1319 static void
1320 sprint_n(char **buf, scf_walkinfo_t *wip)
1321 {
1322         char nstate_name[MAX_SCF_STATE_STRING_SZ + 1];
1323         char tmp[2] = { 0 };


1324 
1325         if (wip->pg == NULL) {
1326                 get_restarter_string_prop(wip->inst, scf_property_next_state,
1327                     nstate_name, sizeof (nstate_name));
1328 
1329                 if (strcmp(nstate_name, SCF_STATE_STRING_NONE) == 0)
1330                         tmp[0] = '-';
1331                 else
1332                         tmp[0] = state_to_char(nstate_name);
1333         } else {
1334                 tmp[0] = '-';
1335         }
1336 
1337         sprint_str(buf, tmp, 1);




1338 }
1339 
1340 static void
1341 sprint_sn(char **buf, scf_walkinfo_t *wip)
1342 {
1343         char state_name[MAX_SCF_STATE_STRING_SZ + 1];
1344         char nstate_name[MAX_SCF_STATE_STRING_SZ + 1];
1345         char tmp[3] = { 0 };


1346 
1347         if (wip->pg == NULL) {
1348                 get_restarter_string_prop(wip->inst, scf_property_state,
1349                     state_name, sizeof (state_name));
1350                 get_restarter_string_prop(wip->inst, scf_property_next_state,
1351                     nstate_name, sizeof (nstate_name));
1352                 tmp[0] = state_to_char(state_name);
1353 
1354                 if (strcmp(nstate_name, SCF_STATE_STRING_NONE) == 0)
1355                         tmp[1] = '-';
1356                 else
1357                         tmp[1] = state_to_char(nstate_name);
1358         } else {
1359                 tmp[0] = 'L';
1360                 tmp[1] = '-';
1361         }
1362 
1363         sprint_str(buf, tmp, 2);





1364 }
1365 
1366 /* ARGSUSED */
1367 static void
1368 sortkey_sn(char *buf, int reverse, scf_walkinfo_t *wip)
1369 {
1370         sortkey_state(buf, reverse, wip);
1371         sortkey_nstate(buf + 1, reverse, wip);
1372 }
1373 
1374 static const char *
1375 state_abbrev(const char *state)
1376 {
1377         if (strcmp(state, SCF_STATE_STRING_UNINIT) == 0)
1378                 return ("UN");
1379         if (strcmp(state, SCF_STATE_STRING_OFFLINE) == 0)
1380                 return ("OFF");
1381         if (strcmp(state, SCF_STATE_STRING_ONLINE) == 0)
1382                 return ("ON");
1383         if (strcmp(state, SCF_STATE_STRING_MAINT) == 0)
1384                 return ("MNT");
1385         if (strcmp(state, SCF_STATE_STRING_DISABLED) == 0)
1386                 return ("DIS");
1387         if (strcmp(state, SCF_STATE_STRING_DEGRADED) == 0)
1388                 return ("DGD");
1389         if (strcmp(state, SCF_STATE_STRING_LEGACY) == 0)
1390                 return ("LRC");
1391 
1392         return ("?");
1393 }
1394 
1395 static void
1396 sprint_sta(char **buf, scf_walkinfo_t *wip)
1397 {
1398         char state_name[MAX_SCF_STATE_STRING_SZ + 1];
1399         char sta[5] = { 0 };


1400 
1401         if (wip->pg == NULL) {
1402                 get_restarter_string_prop(wip->inst, scf_property_state,
1403                     state_name, sizeof (state_name));
1404         } else {
1405                 (void) strcpy(state_name, SCF_STATE_STRING_LEGACY);
1406         }
1407 
1408         (void) strcpy(sta, state_abbrev(state_name));
1409 
1410         if (wip->pg == NULL && !opt_nstate_shown && transitioning(wip->inst))
1411                 (void) strcat(sta, "*");
1412 
1413         sprint_str(buf, sta, 4);



1414 }
1415 
1416 static void
1417 sprint_nsta(char **buf, scf_walkinfo_t *wip)
1418 {
1419         char state_name[MAX_SCF_STATE_STRING_SZ + 1];


1420 
1421         if (wip->pg == NULL) {
1422                 get_restarter_string_prop(wip->inst, scf_property_next_state,
1423                     state_name, sizeof (state_name));
1424         } else {
1425                 (void) strcpy(state_name, SCF_STATE_STRING_NONE);
1426         }
1427 
1428         if (strcmp(state_name, SCF_STATE_STRING_NONE) == 0)
1429                 sprint_str(buf, "-", 4);

1430         else
1431                 sprint_str(buf, state_abbrev(state_name), 4);




1432 }
1433 
1434 /* FMRI */
1435 #define FMRI_COLUMN_WIDTH       50
1436 static void
1437 sprint_fmri(char **buf, scf_walkinfo_t *wip)
1438 {
1439         char *fmri_buf = safe_malloc(max_scf_fmri_length + 1);


1440 
1441         if (wip->pg == NULL) {
1442                 if (scf_instance_to_fmri(wip->inst, fmri_buf,
1443                     max_scf_fmri_length + 1) == -1)
1444                         scfdie();
1445         } else {
1446                 (void) strcpy(fmri_buf, SCF_FMRI_LEGACY_PREFIX);
1447                 if (pg_get_single_val(wip->pg, SCF_LEGACY_PROPERTY_NAME,
1448                     SCF_TYPE_ASTRING, fmri_buf +
1449                     sizeof (SCF_FMRI_LEGACY_PREFIX) - 1,
1450                     max_scf_fmri_length + 1 -
1451                     (sizeof (SCF_FMRI_LEGACY_PREFIX) - 1), 0) != 0)
1452                         (void) strcat(fmri_buf, LEGACY_UNKNOWN);
1453         }
1454 
1455         sprint_str(buf, fmri_buf, FMRI_COLUMN_WIDTH);






1456         free(fmri_buf);



1457 }
1458 
1459 static void
1460 sortkey_fmri(char *buf, int reverse, scf_walkinfo_t *wip)
1461 {
1462         char *tmp = NULL;
1463 
1464         sprint_fmri(&tmp, wip);
1465         bcopy(tmp, buf, FMRI_COLUMN_WIDTH);
1466         free(tmp);
1467         if (reverse)
1468                 reverse_bytes(buf, FMRI_COLUMN_WIDTH);
1469 }
1470 
1471 /* Component columns */
1472 #define COMPONENT_COLUMN_WIDTH  20
1473 static void
1474 sprint_scope(char **buf, scf_walkinfo_t *wip)
1475 {
1476         char *scope_buf = safe_malloc(max_scf_name_length + 1);


1477 
1478         assert(wip->scope != NULL);
1479 
1480         if (scf_scope_get_name(wip->scope, scope_buf, max_scf_name_length) < 0)
1481                 scfdie();
1482 
1483         sprint_str(buf, scope_buf, COMPONENT_COLUMN_WIDTH);




1484         free(scope_buf);
1485 }
1486 
1487 static void
1488 sortkey_scope(char *buf, int reverse, scf_walkinfo_t *wip)
1489 {
1490         char *tmp = NULL;
1491 
1492         sprint_scope(&tmp, wip);
1493         bcopy(tmp, buf, COMPONENT_COLUMN_WIDTH);
1494         free(tmp);
1495         if (reverse)
1496                 reverse_bytes(buf, COMPONENT_COLUMN_WIDTH);
1497 }
1498 
1499 static void
1500 sprint_service(char **buf, scf_walkinfo_t *wip)
1501 {
1502         char *svc_buf = safe_malloc(max_scf_name_length + 1);


1503 
1504         if (wip->pg == NULL) {
1505                 if (scf_service_get_name(wip->svc, svc_buf,
1506                     max_scf_name_length + 1) < 0)
1507                         scfdie();
1508         } else {
1509                 if (pg_get_single_val(wip->pg, "name", SCF_TYPE_ASTRING,
1510                     svc_buf, max_scf_name_length + 1, EMPTY_OK) != 0)
1511                         (void) strcpy(svc_buf, LEGACY_UNKNOWN);
1512         }
1513 
1514         sprint_str(buf, svc_buf, COMPONENT_COLUMN_WIDTH);








1515         free(svc_buf);



1516 }
1517 
1518 static void
1519 sortkey_service(char *buf, int reverse, scf_walkinfo_t *wip)
1520 {
1521         char *tmp = NULL;
1522 
1523         sprint_service(&tmp, wip);
1524         bcopy(tmp, buf, COMPONENT_COLUMN_WIDTH);
1525         free(tmp);
1526         if (reverse)
1527                 reverse_bytes(buf, COMPONENT_COLUMN_WIDTH);
1528 }
1529 
1530 /* INST */
1531 static void
1532 sprint_instance(char **buf, scf_walkinfo_t *wip)
1533 {
1534         char *inst_buf = safe_malloc(max_scf_name_length + 1);


1535 
1536         if (wip->pg == NULL) {
1537                 if (scf_instance_get_name(wip->inst, inst_buf,
1538                     max_scf_name_length + 1) < 0)
1539                         scfdie();
1540         } else {
1541                 inst_buf[0] = '-';
1542                 inst_buf[1] = '\0';
1543         }
1544 
1545 
1546         sprint_str(buf, inst_buf, COMPONENT_COLUMN_WIDTH);
1547         free(inst_buf);



1548 }
1549 
1550 static void
1551 sortkey_instance(char *buf, int reverse, scf_walkinfo_t *wip)
1552 {
1553         char *tmp = NULL;
1554 
1555         sprint_instance(&tmp, wip);
1556         bcopy(tmp, buf, COMPONENT_COLUMN_WIDTH);
1557         free(tmp);
1558         if (reverse)
1559                 reverse_bytes(buf, COMPONENT_COLUMN_WIDTH);
1560 }
1561 
1562 /* STIME */
1563 #define STIME_COLUMN_WIDTH              8
1564 #define FORMAT_TIME                     "%k:%M:%S"
1565 #define FORMAT_DATE                     "%b_%d"
1566 #define FORMAT_YEAR                     "%Y"
1567 
1568 /*
1569  * sprint_stime() will allocate a new buffer and snprintf the services's
1570  * state timestamp.  If the timestamp is unavailable for some reason
1571  * a '-' is given instead.
1572  */
1573 static void
1574 sprint_stime(char **buf, scf_walkinfo_t *wip)
1575 {
1576         int r;
1577         struct timeval tv;
1578         time_t then;
1579         struct tm *tm;
1580         char st_buf[STIME_COLUMN_WIDTH + 1];


1581 
1582         if (wip->pg == NULL) {
1583                 r = get_restarter_time_prop(wip->inst,
1584                     SCF_PROPERTY_STATE_TIMESTAMP, &tv, 0);
1585         } else {
1586                 r = pg_get_single_val(wip->pg, SCF_PROPERTY_STATE_TIMESTAMP,
1587                     SCF_TYPE_TIME, &tv, NULL, 0);
1588         }
1589 
1590         if (r != 0) {
1591                 /*
1592                  * There's something amiss with our service
1593                  * so we'll print a '-' for STIME.
1594                  */
1595                 sprint_str(buf, "-", STIME_COLUMN_WIDTH);

1596         } else {
1597                 /* tv should be valid so we'll format it */
1598                 then = (time_t)tv.tv_sec;
1599 
1600                 tm = localtime(&then);
1601                 /*
1602                  * Print time if started within the past 24 hours, print date
1603                  * if within the past 12 months or, finally, print year if
1604                  * started greater than 12 months ago.
1605                  */
1606                 if (now - then < 24 * 60 * 60) {
1607                         (void) strftime(st_buf, sizeof (st_buf),
1608                             gettext(FORMAT_TIME), tm);
1609                 } else if (now - then < 12 * 30 * 24 * 60 * 60) {
1610                         (void) strftime(st_buf, sizeof (st_buf),
1611                             gettext(FORMAT_DATE), tm);
1612                 } else {
1613                         (void) strftime(st_buf, sizeof (st_buf),
1614                             gettext(FORMAT_YEAR), tm);
1615                 }
1616                 sprint_str(buf, st_buf, STIME_COLUMN_WIDTH);

1617         }



1618 }
1619 
1620 #define STIME_SORTKEY_WIDTH             (sizeof (uint64_t) + sizeof (uint32_t))
1621 
1622 /* ARGSUSED */
1623 static void
1624 sortkey_stime(char *buf, int reverse, scf_walkinfo_t *wip)
1625 {
1626         struct timeval tv;
1627         int r;
1628 
1629         if (wip->pg == NULL)
1630                 r = get_restarter_time_prop(wip->inst,
1631                     SCF_PROPERTY_STATE_TIMESTAMP, &tv, 0);
1632         else
1633                 r = pg_get_single_val(wip->pg, SCF_PROPERTY_STATE_TIMESTAMP,
1634                     SCF_TYPE_TIME, &tv, NULL, 0);
1635 
1636         if (r == 0) {
1637                 int64_t sec;


1642                 us = tv.tv_usec;
1643 
1644                 sec = BE_64(sec);
1645                 us = BE_32(us);
1646                 bcopy(&sec, buf, sizeof (sec));
1647                 bcopy(&us, buf + sizeof (sec), sizeof (us));
1648         } else {
1649                 bzero(buf, STIME_SORTKEY_WIDTH);
1650         }
1651 
1652         if (reverse)
1653                 reverse_bytes(buf, STIME_SORTKEY_WIDTH);
1654 }
1655 
1656 /* ZONE */
1657 #define ZONE_COLUMN_WIDTH       16
1658 /*ARGSUSED*/
1659 static void
1660 sprint_zone(char **buf, scf_walkinfo_t *wip)
1661 {
1662         char *zonename = g_zonename, b[ZONENAME_MAX];

1663 
1664         if (zonename == NULL) {
1665                 zoneid_t zoneid = getzoneid();
1666 
1667                 if (getzonenamebyid(zoneid, b, sizeof (b)) < 0)
1668                         uu_die(gettext("could not determine zone name"));
1669 
1670                 zonename = b;
1671         }
1672 
1673         sprint_str(buf, zonename, ZONE_COLUMN_WIDTH);











1674 }
1675 
1676 static void
1677 sortkey_zone(char *buf, int reverse, scf_walkinfo_t *wip)
1678 {
1679         char *tmp = NULL;
1680 
1681         sprint_zone(&tmp, wip);
1682         bcopy(tmp, buf, ZONE_COLUMN_WIDTH);
1683         free(tmp);
1684         if (reverse)
1685                 reverse_bytes(buf, ZONE_COLUMN_WIDTH);
1686 }
1687 
1688 /*
1689  * Information about columns which can be displayed.  If you add something,
1690  * check MAX_COLUMN_NAME_LENGTH_STR & update description_of_column() below.
1691  */
1692 static const struct column columns[] = {
1693         { "CTID", CTID_COLUMN_WIDTH, sprint_ctid,
1694                 CTID_SORTKEY_WIDTH, sortkey_ctid },
1695         { "DESC", DESC_COLUMN_WIDTH, sprint_desc,
1696                 DESC_COLUMN_WIDTH, sortkey_desc },
1697         { "FMRI", FMRI_COLUMN_WIDTH, sprint_fmri,
1698                 FMRI_COLUMN_WIDTH, sortkey_fmri },
1699         { "INST", COMPONENT_COLUMN_WIDTH, sprint_instance,
1700                 COMPONENT_COLUMN_WIDTH, sortkey_instance },
1701         { "N", 1,  sprint_n, 1, sortkey_nstate },
1702         { "NSTA", 4, sprint_nsta, 1, sortkey_nstate },
1703         { "NSTATE", MAX_SCF_STATE_STRING_SZ, sprint_nstate,
1704                 1, sortkey_nstate },
1705         { "S", 2, sprint_s, 1, sortkey_state },
1706         { "SCOPE", COMPONENT_COLUMN_WIDTH, sprint_scope,
1707                 COMPONENT_COLUMN_WIDTH, sortkey_scope },
1708         { "SN", 2, sprint_sn, 2, sortkey_sn },
1709         { "SVC", COMPONENT_COLUMN_WIDTH, sprint_service,
1710                 COMPONENT_COLUMN_WIDTH, sortkey_service },
1711         { "STA", 4, sprint_sta, 1, sortkey_state },
1712         { "STATE", MAX_SCF_STATE_STRING_SZ, sprint_state,
1713                 1, sortkey_state },
1714         { "STIME", STIME_COLUMN_WIDTH, sprint_stime,
1715                 STIME_SORTKEY_WIDTH, sortkey_stime },
1716         { "ZONE", ZONE_COLUMN_WIDTH, sprint_zone,
1717                 ZONE_COLUMN_WIDTH, sortkey_zone },
1718 };
1719 
1720 #define MAX_COLUMN_NAME_LENGTH_STR      "6"
1721 
1722 static const int ncolumns = sizeof (columns) / sizeof (columns[0]);
1723 
1724 /*
1725  * Necessary thanks to gettext() & xgettext.
1726  */
1727 static const char *
1728 description_of_column(int c)
1729 {
1730         const char *s = NULL;
1731 
1732         switch (c) {


1768                 break;
1769         case 12:
1770                 s = gettext("name for current state");
1771                 break;
1772         case 13:
1773                 s = gettext("time of last state change");
1774                 break;
1775         case 14:
1776                 s = gettext("name of zone");
1777                 break;
1778         }
1779 
1780         assert(s != NULL);
1781         return (s);
1782 }
1783 
1784 
1785 static void
1786 print_usage(const char *progname, FILE *f, boolean_t do_exit)
1787 {
1788         (void) fprintf(f, gettext("usage:\n"
1789             "%1$s\t[-aHpv?] [-o col[,col]...] [-R FMRI-instance]... "
1790             "[-sS col]...\n\t[-z zone|-Z] [FMRI|pattern]...\n"
1791             "%1$s\t{-d|-D} -Hpv? [-o col[,col]...] [-sS col]... [-z zone|-Z]\n"
1792             "\t[FMRI|pattern]...\n"
1793             "%1$s\t{-l|-L} [-v] [-z zone|-Z] {FMRI|pattern}...\n"
1794             "%1$s\t-x [-v] [-z zone|-Z] [FMRI]...\n"), progname);

1795 
1796         if (do_exit)
1797                 exit(UU_EXIT_USAGE);
1798 }
1799 
1800 #define argserr(progname)       print_usage(progname, stderr, B_TRUE)
1801 
1802 static void
1803 print_help(const char *progname)
1804 {
1805         int i;
1806 
1807         print_usage(progname, stdout, B_FALSE);
1808 
1809         (void) printf(gettext("\n"
1810         "\t-a  list all service instances rather than "
1811         "only those that are enabled\n"
1812         "\t-d  list dependencies of the specified service(s)\n"
1813         "\t-D  list dependents of the specified service(s)\n"
1814         "\t-H  omit header line from output\n"


3352 /* ARGSUSED */
3353 static void
3354 errignore(const char *str, ...)
3355 {}
3356 
3357 int
3358 main(int argc, char **argv)
3359 {
3360         char opt, opt_mode;
3361         int i, n;
3362         char *columns_str = NULL;
3363         char *cp;
3364         const char *progname;
3365         int err, missing = 1, ignored, *errarg;
3366         uint_t nzents = 0, zent = 0;
3367         zoneid_t *zids = NULL;
3368         char zonename[ZONENAME_MAX];
3369         void (*errfunc)(const char *, ...);
3370 
3371         int show_all = 0;

3372         int show_zones = 0;
3373 
3374         const char * const options = "aHpvno:R:s:S:dDlL?xZz:";
3375 
3376         (void) setlocale(LC_ALL, "");
3377 
3378         locale = setlocale(LC_MESSAGES, NULL);
3379         if (locale) {
3380                 locale = safe_strdup(locale);
3381                 _scf_sanitize_locale(locale);
3382         }
3383 
3384         (void) textdomain(TEXT_DOMAIN);
3385         progname = uu_setpname(argv[0]);
3386 
3387         exit_status = UU_EXIT_OK;
3388 
3389         max_scf_name_length = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH);
3390         max_scf_value_length = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH);
3391         max_scf_fmri_length = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH);


3441 
3442                 default:
3443                         break;
3444                 }
3445         }
3446 
3447         sortkey_sz = 0;
3448 
3449         optind = 1;     /* Reset getopt() */
3450         while ((opt = getopt(argc, argv, options)) != -1) {
3451                 switch (opt) {
3452                 case 'a':
3453                         if (opt_mode != 0)
3454                                 argserr(progname);
3455                         show_all = 1;
3456                         break;
3457 
3458                 case 'H':
3459                         if (opt_mode == 'l' || opt_mode == 'x')
3460                                 argserr(progname);
3461                         opt_scripted = 1;
3462                         break;
3463 
3464                 case 'p':
3465                         if (opt_mode == 'x')
3466                                 argserr(progname);
3467                         opt_processes = 1;
3468                         break;
3469 
3470                 case 'v':
3471                         opt_verbose = 1;
3472                         break;
3473 
3474                 case 'o':
3475                         if (opt_mode == 'l' || opt_mode == 'x')
3476                                 argserr(progname);
3477                         columns_str = optarg;
3478                         break;
3479 
3480                 case 'R':
3481                         if (opt_mode != 0 || opt_mode == 'x')


3820         case 'n':
3821                 break;
3822 
3823         default:
3824                 assert(0);
3825                 abort();
3826         }
3827 
3828 nextzone:
3829         if (show_zones && zent < nzents && exit_status == 0) {
3830                 scf_handle_destroy(h);
3831                 goto again;
3832         }
3833 
3834         if (show_zones && exit_status == 0)
3835                 exit_status = missing;
3836 
3837         if (opt_columns == NULL)
3838                 return (exit_status);
3839 
3840         if (!opt_scripted)
3841                 print_header();
3842 
3843         (void) uu_avl_walk(lines, print_line, NULL, 0);
3844 
3845         return (exit_status);
3846 }