536 /*
537 * Get a string property from the restarter property group of the given
538 * instance. Return an empty string on normal problems.
539 */
540 static void
541 get_restarter_string_prop(scf_instance_t *inst, const char *pname,
542 char *buf, size_t buf_sz)
543 {
544 if (inst_get_single_val(inst, SCF_PG_RESTARTER, pname,
545 SCF_TYPE_ASTRING, buf, buf_sz, 0, 0, 1) != 0)
546 *buf = '\0';
547 }
548
549 static int
550 get_restarter_time_prop(scf_instance_t *inst, const char *pname,
551 struct timeval *tvp, int ok_if_empty)
552 {
553 int r;
554
555 r = inst_get_single_val(inst, SCF_PG_RESTARTER, pname, SCF_TYPE_TIME,
556 tvp, NULL, ok_if_empty ? EMPTY_OK : 0, 0, 1);
557
558 return (r == 0 ? 0 : -1);
559 }
560
561 static int
562 get_restarter_count_prop(scf_instance_t *inst, const char *pname, uint64_t *cp,
563 uint_t flags)
564 {
565 return (inst_get_single_val(inst, SCF_PG_RESTARTER, pname,
566 SCF_TYPE_COUNT, cp, 0, flags, 0, 1));
567 }
568
569
570 /*
571 * Generic functions
572 */
573
574 /*
575 * Return an array of pids associated with the given contract id.
576 * Returned pids are added to the end of the pidsp array.
1633 * sprint_stime() will allocate a new buffer and snprintf the services's
1634 * state timestamp. If the timestamp is unavailable for some reason
1635 * a '-' is given instead.
1636 */
1637 static void
1638 sprint_stime(char **buf, scf_walkinfo_t *wip)
1639 {
1640 int r;
1641 struct timeval tv;
1642 time_t then;
1643 struct tm *tm;
1644 char st_buf[STIME_COLUMN_WIDTH + 1];
1645 size_t newsize = (*buf ? strlen(*buf) : 0) + STIME_COLUMN_WIDTH + 2;
1646 char *newbuf = safe_malloc(newsize);
1647
1648 if (wip->pg == NULL) {
1649 r = get_restarter_time_prop(wip->inst,
1650 SCF_PROPERTY_STATE_TIMESTAMP, &tv, 0);
1651 } else {
1652 r = pg_get_single_val(wip->pg, SCF_PROPERTY_STATE_TIMESTAMP,
1653 SCF_TYPE_TIME, &tv, NULL, 0);
1654 }
1655
1656 if (r != 0) {
1657 /*
1658 * There's something amiss with our service
1659 * so we'll print a '-' for STIME.
1660 */
1661 (void) snprintf(newbuf, newsize, "%s%-*s", *buf ? *buf : "",
1662 STIME_COLUMN_WIDTH + 1, "-");
1663 } else {
1664 /* tv should be valid so we'll format it */
1665 then = (time_t)tv.tv_sec;
1666
1667 tm = localtime(&then);
1668 /*
1669 * Print time if started within the past 24 hours, print date
1670 * if within the past 12 months or, finally, print year if
1671 * started greater than 12 months ago.
1672 */
1673 if (now - then < 24 * 60 * 60) {
1685 }
1686 if (*buf)
1687 free(*buf);
1688 *buf = newbuf;
1689 }
1690
1691 #define STIME_SORTKEY_WIDTH (sizeof (uint64_t) + sizeof (uint32_t))
1692
1693 /* ARGSUSED */
1694 static void
1695 sortkey_stime(char *buf, int reverse, scf_walkinfo_t *wip)
1696 {
1697 struct timeval tv;
1698 int r;
1699
1700 if (wip->pg == NULL)
1701 r = get_restarter_time_prop(wip->inst,
1702 SCF_PROPERTY_STATE_TIMESTAMP, &tv, 0);
1703 else
1704 r = pg_get_single_val(wip->pg, SCF_PROPERTY_STATE_TIMESTAMP,
1705 SCF_TYPE_TIME, &tv, NULL, 0);
1706
1707 if (r == 0) {
1708 int64_t sec;
1709 int32_t us;
1710
1711 /* Stick it straight into the buffer. */
1712 sec = tv.tv_sec;
1713 us = tv.tv_usec;
1714
1715 sec = BE_64(sec);
1716 us = BE_32(us);
1717 bcopy(&sec, buf, sizeof (sec));
1718 bcopy(&us, buf + sizeof (sec), sizeof (us));
1719 } else {
1720 bzero(buf, STIME_SORTKEY_WIDTH);
1721 }
1722
1723 if (reverse)
1724 reverse_bytes(buf, STIME_SORTKEY_WIDTH);
1725 }
2497 if (scf_instance_get_pg(wip->inst, SCF_PG_RESTARTER, rpg) != 0) {
2498 if (scf_error() != SCF_ERROR_NOT_FOUND)
2499 scfdie();
2500
2501 scf_pg_destroy(rpg);
2502 rpg = NULL;
2503 }
2504
2505 if (rpg) {
2506 if (pg_get_single_val(rpg, scf_property_state, SCF_TYPE_ASTRING,
2507 buf, max_scf_fmri_length + 1, 0) == 0)
2508 (void) printf(fmt, DETAILED_WIDTH, gettext("state"),
2509 buf);
2510
2511 if (pg_get_single_val(rpg, scf_property_next_state,
2512 SCF_TYPE_ASTRING, buf, max_scf_fmri_length + 1, 0) == 0)
2513 (void) printf(fmt, DETAILED_WIDTH,
2514 gettext("next_state"), buf);
2515
2516 if (pg_get_single_val(rpg, SCF_PROPERTY_STATE_TIMESTAMP,
2517 SCF_TYPE_TIME, &tv, NULL, 0) == 0) {
2518 stime = tv.tv_sec;
2519 tmp = localtime(&stime);
2520 for (tbsz = 50; ; tbsz *= 2) {
2521 timebuf = safe_malloc(tbsz);
2522 if (strftime(timebuf, tbsz, NULL, tmp) != 0)
2523 break;
2524 free(timebuf);
2525 }
2526 (void) printf(fmt, DETAILED_WIDTH,
2527 gettext("state_time"),
2528 timebuf);
2529 free(timebuf);
2530 }
2531
2532 if (pg_get_single_val(rpg, SCF_PROPERTY_ALT_LOGFILE,
2533 SCF_TYPE_ASTRING, buf, max_scf_fmri_length + 1, 0) == 0)
2534 (void) printf(fmt, DETAILED_WIDTH,
2535 gettext("alt_logfile"), buf);
2536
2537 if (pg_get_single_val(rpg, SCF_PROPERTY_LOGFILE,
|
536 /*
537 * Get a string property from the restarter property group of the given
538 * instance. Return an empty string on normal problems.
539 */
540 static void
541 get_restarter_string_prop(scf_instance_t *inst, const char *pname,
542 char *buf, size_t buf_sz)
543 {
544 if (inst_get_single_val(inst, SCF_PG_RESTARTER, pname,
545 SCF_TYPE_ASTRING, buf, buf_sz, 0, 0, 1) != 0)
546 *buf = '\0';
547 }
548
549 static int
550 get_restarter_time_prop(scf_instance_t *inst, const char *pname,
551 struct timeval *tvp, int ok_if_empty)
552 {
553 int r;
554
555 r = inst_get_single_val(inst, SCF_PG_RESTARTER, pname, SCF_TYPE_TIME,
556 tvp, 0, ok_if_empty ? EMPTY_OK : 0, 0, 1);
557
558 return (r == 0 ? 0 : -1);
559 }
560
561 static int
562 get_restarter_count_prop(scf_instance_t *inst, const char *pname, uint64_t *cp,
563 uint_t flags)
564 {
565 return (inst_get_single_val(inst, SCF_PG_RESTARTER, pname,
566 SCF_TYPE_COUNT, cp, 0, flags, 0, 1));
567 }
568
569
570 /*
571 * Generic functions
572 */
573
574 /*
575 * Return an array of pids associated with the given contract id.
576 * Returned pids are added to the end of the pidsp array.
1633 * sprint_stime() will allocate a new buffer and snprintf the services's
1634 * state timestamp. If the timestamp is unavailable for some reason
1635 * a '-' is given instead.
1636 */
1637 static void
1638 sprint_stime(char **buf, scf_walkinfo_t *wip)
1639 {
1640 int r;
1641 struct timeval tv;
1642 time_t then;
1643 struct tm *tm;
1644 char st_buf[STIME_COLUMN_WIDTH + 1];
1645 size_t newsize = (*buf ? strlen(*buf) : 0) + STIME_COLUMN_WIDTH + 2;
1646 char *newbuf = safe_malloc(newsize);
1647
1648 if (wip->pg == NULL) {
1649 r = get_restarter_time_prop(wip->inst,
1650 SCF_PROPERTY_STATE_TIMESTAMP, &tv, 0);
1651 } else {
1652 r = pg_get_single_val(wip->pg, SCF_PROPERTY_STATE_TIMESTAMP,
1653 SCF_TYPE_TIME, &tv, 0, 0);
1654 }
1655
1656 if (r != 0) {
1657 /*
1658 * There's something amiss with our service
1659 * so we'll print a '-' for STIME.
1660 */
1661 (void) snprintf(newbuf, newsize, "%s%-*s", *buf ? *buf : "",
1662 STIME_COLUMN_WIDTH + 1, "-");
1663 } else {
1664 /* tv should be valid so we'll format it */
1665 then = (time_t)tv.tv_sec;
1666
1667 tm = localtime(&then);
1668 /*
1669 * Print time if started within the past 24 hours, print date
1670 * if within the past 12 months or, finally, print year if
1671 * started greater than 12 months ago.
1672 */
1673 if (now - then < 24 * 60 * 60) {
1685 }
1686 if (*buf)
1687 free(*buf);
1688 *buf = newbuf;
1689 }
1690
1691 #define STIME_SORTKEY_WIDTH (sizeof (uint64_t) + sizeof (uint32_t))
1692
1693 /* ARGSUSED */
1694 static void
1695 sortkey_stime(char *buf, int reverse, scf_walkinfo_t *wip)
1696 {
1697 struct timeval tv;
1698 int r;
1699
1700 if (wip->pg == NULL)
1701 r = get_restarter_time_prop(wip->inst,
1702 SCF_PROPERTY_STATE_TIMESTAMP, &tv, 0);
1703 else
1704 r = pg_get_single_val(wip->pg, SCF_PROPERTY_STATE_TIMESTAMP,
1705 SCF_TYPE_TIME, &tv, 0, 0);
1706
1707 if (r == 0) {
1708 int64_t sec;
1709 int32_t us;
1710
1711 /* Stick it straight into the buffer. */
1712 sec = tv.tv_sec;
1713 us = tv.tv_usec;
1714
1715 sec = BE_64(sec);
1716 us = BE_32(us);
1717 bcopy(&sec, buf, sizeof (sec));
1718 bcopy(&us, buf + sizeof (sec), sizeof (us));
1719 } else {
1720 bzero(buf, STIME_SORTKEY_WIDTH);
1721 }
1722
1723 if (reverse)
1724 reverse_bytes(buf, STIME_SORTKEY_WIDTH);
1725 }
2497 if (scf_instance_get_pg(wip->inst, SCF_PG_RESTARTER, rpg) != 0) {
2498 if (scf_error() != SCF_ERROR_NOT_FOUND)
2499 scfdie();
2500
2501 scf_pg_destroy(rpg);
2502 rpg = NULL;
2503 }
2504
2505 if (rpg) {
2506 if (pg_get_single_val(rpg, scf_property_state, SCF_TYPE_ASTRING,
2507 buf, max_scf_fmri_length + 1, 0) == 0)
2508 (void) printf(fmt, DETAILED_WIDTH, gettext("state"),
2509 buf);
2510
2511 if (pg_get_single_val(rpg, scf_property_next_state,
2512 SCF_TYPE_ASTRING, buf, max_scf_fmri_length + 1, 0) == 0)
2513 (void) printf(fmt, DETAILED_WIDTH,
2514 gettext("next_state"), buf);
2515
2516 if (pg_get_single_val(rpg, SCF_PROPERTY_STATE_TIMESTAMP,
2517 SCF_TYPE_TIME, &tv, 0, 0) == 0) {
2518 stime = tv.tv_sec;
2519 tmp = localtime(&stime);
2520 for (tbsz = 50; ; tbsz *= 2) {
2521 timebuf = safe_malloc(tbsz);
2522 if (strftime(timebuf, tbsz, NULL, tmp) != 0)
2523 break;
2524 free(timebuf);
2525 }
2526 (void) printf(fmt, DETAILED_WIDTH,
2527 gettext("state_time"),
2528 timebuf);
2529 free(timebuf);
2530 }
2531
2532 if (pg_get_single_val(rpg, SCF_PROPERTY_ALT_LOGFILE,
2533 SCF_TYPE_ASTRING, buf, max_scf_fmri_length + 1, 0) == 0)
2534 (void) printf(fmt, DETAILED_WIDTH,
2535 gettext("alt_logfile"), buf);
2536
2537 if (pg_get_single_val(rpg, SCF_PROPERTY_LOGFILE,
|