1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 3*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 4*7c478bd9Sstevel@tonic-gate */ 5*7c478bd9Sstevel@tonic-gate 6*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 7*7c478bd9Sstevel@tonic-gate 8*7c478bd9Sstevel@tonic-gate /* 9*7c478bd9Sstevel@tonic-gate * This module will parse the update logs on the master or slave servers. 10*7c478bd9Sstevel@tonic-gate */ 11*7c478bd9Sstevel@tonic-gate 12*7c478bd9Sstevel@tonic-gate #include <stdio.h> 13*7c478bd9Sstevel@tonic-gate #include <libintl.h> 14*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 15*7c478bd9Sstevel@tonic-gate #include <time.h> 16*7c478bd9Sstevel@tonic-gate #include <limits.h> 17*7c478bd9Sstevel@tonic-gate #include <locale.h> 18*7c478bd9Sstevel@tonic-gate #include <syslog.h> 19*7c478bd9Sstevel@tonic-gate #include <kdb/kdb_log.h> 20*7c478bd9Sstevel@tonic-gate #include <kadm5/admin.h> 21*7c478bd9Sstevel@tonic-gate 22*7c478bd9Sstevel@tonic-gate static char *progname; 23*7c478bd9Sstevel@tonic-gate 24*7c478bd9Sstevel@tonic-gate static void 25*7c478bd9Sstevel@tonic-gate usage() 26*7c478bd9Sstevel@tonic-gate { 27*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("\nUsage: %s [-h] [-v] [-e num]\n\n"), 28*7c478bd9Sstevel@tonic-gate progname); 29*7c478bd9Sstevel@tonic-gate exit(1); 30*7c478bd9Sstevel@tonic-gate } 31*7c478bd9Sstevel@tonic-gate 32*7c478bd9Sstevel@tonic-gate /* 33*7c478bd9Sstevel@tonic-gate * Print the individual types if verbose mode was specified. 34*7c478bd9Sstevel@tonic-gate */ 35*7c478bd9Sstevel@tonic-gate static void 36*7c478bd9Sstevel@tonic-gate print_attr(kdbe_attr_type_t type) 37*7c478bd9Sstevel@tonic-gate { 38*7c478bd9Sstevel@tonic-gate switch (type) { 39*7c478bd9Sstevel@tonic-gate case AT_ATTRFLAGS: 40*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\t\tAttribute flags\n")); 41*7c478bd9Sstevel@tonic-gate break; 42*7c478bd9Sstevel@tonic-gate case AT_MAX_LIFE: 43*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\t\tMaximum ticket life\n")); 44*7c478bd9Sstevel@tonic-gate break; 45*7c478bd9Sstevel@tonic-gate case AT_MAX_RENEW_LIFE: 46*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\t\tMaximum renewable life\n")); 47*7c478bd9Sstevel@tonic-gate break; 48*7c478bd9Sstevel@tonic-gate case AT_EXP: 49*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\t\tPrincipal expiration\n")); 50*7c478bd9Sstevel@tonic-gate break; 51*7c478bd9Sstevel@tonic-gate case AT_PW_EXP: 52*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\t\tPassword expiration\n")); 53*7c478bd9Sstevel@tonic-gate break; 54*7c478bd9Sstevel@tonic-gate case AT_LAST_SUCCESS: 55*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\t\tLast successful auth\n")); 56*7c478bd9Sstevel@tonic-gate break; 57*7c478bd9Sstevel@tonic-gate case AT_LAST_FAILED: 58*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\t\tLast failed auth\n")); 59*7c478bd9Sstevel@tonic-gate break; 60*7c478bd9Sstevel@tonic-gate case AT_FAIL_AUTH_COUNT: 61*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\t\tFailed passwd attempt\n")); 62*7c478bd9Sstevel@tonic-gate break; 63*7c478bd9Sstevel@tonic-gate case AT_PRINC: 64*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\t\tPrincipal\n")); 65*7c478bd9Sstevel@tonic-gate break; 66*7c478bd9Sstevel@tonic-gate case AT_KEYDATA: 67*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\t\tKey data\n")); 68*7c478bd9Sstevel@tonic-gate break; 69*7c478bd9Sstevel@tonic-gate case AT_TL_DATA: 70*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\t\tTL data\n")); 71*7c478bd9Sstevel@tonic-gate break; 72*7c478bd9Sstevel@tonic-gate case AT_LEN: 73*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\t\tLength\n")); 74*7c478bd9Sstevel@tonic-gate break; 75*7c478bd9Sstevel@tonic-gate case AT_MOD_PRINC: 76*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\t\tModifying principal\n")); 77*7c478bd9Sstevel@tonic-gate break; 78*7c478bd9Sstevel@tonic-gate case AT_MOD_TIME: 79*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\t\tModification time\n")); 80*7c478bd9Sstevel@tonic-gate break; 81*7c478bd9Sstevel@tonic-gate case AT_MOD_WHERE: 82*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\t\tModified where\n")); 83*7c478bd9Sstevel@tonic-gate break; 84*7c478bd9Sstevel@tonic-gate case AT_PW_LAST_CHANGE: 85*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\t\tPassword last changed\n")); 86*7c478bd9Sstevel@tonic-gate break; 87*7c478bd9Sstevel@tonic-gate case AT_PW_POLICY: 88*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\t\tPassword policy\n")); 89*7c478bd9Sstevel@tonic-gate break; 90*7c478bd9Sstevel@tonic-gate case AT_PW_POLICY_SWITCH: 91*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\t\tPassword policy switch\n")); 92*7c478bd9Sstevel@tonic-gate break; 93*7c478bd9Sstevel@tonic-gate case AT_PW_HIST_KVNO: 94*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\t\tPassword history KVNO\n")); 95*7c478bd9Sstevel@tonic-gate break; 96*7c478bd9Sstevel@tonic-gate case AT_PW_HIST: 97*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\t\tPassword history\n")); 98*7c478bd9Sstevel@tonic-gate break; 99*7c478bd9Sstevel@tonic-gate } /* switch */ 100*7c478bd9Sstevel@tonic-gate 101*7c478bd9Sstevel@tonic-gate } 102*7c478bd9Sstevel@tonic-gate /* 103*7c478bd9Sstevel@tonic-gate * Print the update entry information 104*7c478bd9Sstevel@tonic-gate */ 105*7c478bd9Sstevel@tonic-gate static void 106*7c478bd9Sstevel@tonic-gate print_update(kdb_hlog_t *ulog, uint32_t entry, bool_t verbose) 107*7c478bd9Sstevel@tonic-gate { 108*7c478bd9Sstevel@tonic-gate XDR xdrs; 109*7c478bd9Sstevel@tonic-gate uint32_t start_sno, i, j, indx; 110*7c478bd9Sstevel@tonic-gate char *dbprinc; 111*7c478bd9Sstevel@tonic-gate kdb_ent_header_t *indx_log; 112*7c478bd9Sstevel@tonic-gate kdb_incr_update_t upd; 113*7c478bd9Sstevel@tonic-gate 114*7c478bd9Sstevel@tonic-gate if (entry && (entry < ulog->kdb_num)) 115*7c478bd9Sstevel@tonic-gate start_sno = ulog->kdb_last_sno - entry; 116*7c478bd9Sstevel@tonic-gate else 117*7c478bd9Sstevel@tonic-gate start_sno = ulog->kdb_first_sno - 1; 118*7c478bd9Sstevel@tonic-gate 119*7c478bd9Sstevel@tonic-gate for (i = start_sno; i < ulog->kdb_last_sno; i++) { 120*7c478bd9Sstevel@tonic-gate indx = i % ulog->kdb_num; 121*7c478bd9Sstevel@tonic-gate 122*7c478bd9Sstevel@tonic-gate indx_log = (kdb_ent_header_t *)INDEX(ulog, indx); 123*7c478bd9Sstevel@tonic-gate 124*7c478bd9Sstevel@tonic-gate /* 125*7c478bd9Sstevel@tonic-gate * Check for corrupt update entry 126*7c478bd9Sstevel@tonic-gate */ 127*7c478bd9Sstevel@tonic-gate if (indx_log->kdb_umagic != KDB_UMAGIC) { 128*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 129*7c478bd9Sstevel@tonic-gate gettext("Corrupt update entry\n\n")); 130*7c478bd9Sstevel@tonic-gate exit(1); 131*7c478bd9Sstevel@tonic-gate } 132*7c478bd9Sstevel@tonic-gate 133*7c478bd9Sstevel@tonic-gate (void) memset((char *)&upd, 0, sizeof (kdb_incr_update_t)); 134*7c478bd9Sstevel@tonic-gate xdrmem_create(&xdrs, (char *)indx_log->entry_data, 135*7c478bd9Sstevel@tonic-gate indx_log->kdb_entry_size, XDR_DECODE); 136*7c478bd9Sstevel@tonic-gate if (!xdr_kdb_incr_update_t(&xdrs, &upd)) { 137*7c478bd9Sstevel@tonic-gate (void) printf(gettext("Entry data decode failure\n\n")); 138*7c478bd9Sstevel@tonic-gate exit(1); 139*7c478bd9Sstevel@tonic-gate } 140*7c478bd9Sstevel@tonic-gate 141*7c478bd9Sstevel@tonic-gate (void) printf("---\n"); 142*7c478bd9Sstevel@tonic-gate (void) printf(gettext("Update Entry\n")); 143*7c478bd9Sstevel@tonic-gate 144*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\tUpdate serial # : %u\n"), 145*7c478bd9Sstevel@tonic-gate indx_log->kdb_entry_sno); 146*7c478bd9Sstevel@tonic-gate 147*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\tUpdate operation : ")); 148*7c478bd9Sstevel@tonic-gate if (upd.kdb_deleted) 149*7c478bd9Sstevel@tonic-gate (void) printf(gettext("Delete\n")); 150*7c478bd9Sstevel@tonic-gate else 151*7c478bd9Sstevel@tonic-gate (void) printf(gettext("Add\n")); 152*7c478bd9Sstevel@tonic-gate 153*7c478bd9Sstevel@tonic-gate dbprinc = malloc(upd.kdb_princ_name.utf8str_t_len + 1); 154*7c478bd9Sstevel@tonic-gate if (dbprinc == NULL) { 155*7c478bd9Sstevel@tonic-gate (void) printf(gettext("Could not allocate " 156*7c478bd9Sstevel@tonic-gate "principal name\n\n")); 157*7c478bd9Sstevel@tonic-gate exit(1); 158*7c478bd9Sstevel@tonic-gate } 159*7c478bd9Sstevel@tonic-gate (void) strlcpy(dbprinc, upd.kdb_princ_name.utf8str_t_val, 160*7c478bd9Sstevel@tonic-gate (upd.kdb_princ_name.utf8str_t_len + 1)); 161*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\tUpdate principal : %s\n"), dbprinc); 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\tUpdate size : %u\n"), 164*7c478bd9Sstevel@tonic-gate indx_log->kdb_entry_size); 165*7c478bd9Sstevel@tonic-gate 166*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\tUpdate committed : %s\n"), 167*7c478bd9Sstevel@tonic-gate indx_log->kdb_commit ? "True" : "False"); 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate if (indx_log->kdb_time.seconds == 0L) 170*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\tUpdate time stamp : None\n")); 171*7c478bd9Sstevel@tonic-gate else 172*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\tUpdate time stamp : %s"), 173*7c478bd9Sstevel@tonic-gate ctime((time_t *)&(indx_log->kdb_time.seconds))); 174*7c478bd9Sstevel@tonic-gate 175*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\tAttributes changed : %d\n"), 176*7c478bd9Sstevel@tonic-gate upd.kdb_update.kdbe_t_len); 177*7c478bd9Sstevel@tonic-gate 178*7c478bd9Sstevel@tonic-gate if (verbose) 179*7c478bd9Sstevel@tonic-gate for (j = 0; j < upd.kdb_update.kdbe_t_len; j++) 180*7c478bd9Sstevel@tonic-gate print_attr( 181*7c478bd9Sstevel@tonic-gate upd.kdb_update.kdbe_t_val[j].av_type); 182*7c478bd9Sstevel@tonic-gate 183*7c478bd9Sstevel@tonic-gate xdr_free(xdr_kdb_incr_update_t, (char *)&upd); 184*7c478bd9Sstevel@tonic-gate if (dbprinc) 185*7c478bd9Sstevel@tonic-gate free(dbprinc); 186*7c478bd9Sstevel@tonic-gate } /* for */ 187*7c478bd9Sstevel@tonic-gate } 188*7c478bd9Sstevel@tonic-gate 189*7c478bd9Sstevel@tonic-gate int 190*7c478bd9Sstevel@tonic-gate main(int argc, char **argv) 191*7c478bd9Sstevel@tonic-gate { 192*7c478bd9Sstevel@tonic-gate int c; 193*7c478bd9Sstevel@tonic-gate bool_t verbose = FALSE; 194*7c478bd9Sstevel@tonic-gate bool_t headeronly = FALSE; 195*7c478bd9Sstevel@tonic-gate uint32_t entry = 0; 196*7c478bd9Sstevel@tonic-gate krb5_context context; 197*7c478bd9Sstevel@tonic-gate kadm5_config_params params; 198*7c478bd9Sstevel@tonic-gate kdb_log_context *log_ctx; 199*7c478bd9Sstevel@tonic-gate kdb_hlog_t *ulog = NULL; 200*7c478bd9Sstevel@tonic-gate 201*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 202*7c478bd9Sstevel@tonic-gate 203*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 204*7c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 205*7c478bd9Sstevel@tonic-gate #endif /* TEXT_DOMAIN */ 206*7c478bd9Sstevel@tonic-gate 207*7c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 208*7c478bd9Sstevel@tonic-gate 209*7c478bd9Sstevel@tonic-gate if (geteuid() != (uid_t)0) { 210*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 211*7c478bd9Sstevel@tonic-gate gettext("kproplog must be run as root\n\n")); 212*7c478bd9Sstevel@tonic-gate exit(1); 213*7c478bd9Sstevel@tonic-gate } 214*7c478bd9Sstevel@tonic-gate 215*7c478bd9Sstevel@tonic-gate progname = argv[0]; 216*7c478bd9Sstevel@tonic-gate 217*7c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "vhe:")) != -1) { 218*7c478bd9Sstevel@tonic-gate switch (c) { 219*7c478bd9Sstevel@tonic-gate case 'h': 220*7c478bd9Sstevel@tonic-gate headeronly = TRUE; 221*7c478bd9Sstevel@tonic-gate break; 222*7c478bd9Sstevel@tonic-gate case 'e': 223*7c478bd9Sstevel@tonic-gate entry = atoi(optarg); 224*7c478bd9Sstevel@tonic-gate break; 225*7c478bd9Sstevel@tonic-gate case 'v': 226*7c478bd9Sstevel@tonic-gate verbose = TRUE; 227*7c478bd9Sstevel@tonic-gate break; 228*7c478bd9Sstevel@tonic-gate default: 229*7c478bd9Sstevel@tonic-gate usage(); 230*7c478bd9Sstevel@tonic-gate } 231*7c478bd9Sstevel@tonic-gate } 232*7c478bd9Sstevel@tonic-gate 233*7c478bd9Sstevel@tonic-gate if (krb5_init_context(&context)) { 234*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 235*7c478bd9Sstevel@tonic-gate gettext("Unable to initialize Kerberos\n\n")); 236*7c478bd9Sstevel@tonic-gate exit(1); 237*7c478bd9Sstevel@tonic-gate } 238*7c478bd9Sstevel@tonic-gate 239*7c478bd9Sstevel@tonic-gate (void) memset((char *)¶ms, 0, sizeof (params)); 240*7c478bd9Sstevel@tonic-gate 241*7c478bd9Sstevel@tonic-gate if (kadm5_get_config_params(context, NULL, NULL, ¶ms, ¶ms)) { 242*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 243*7c478bd9Sstevel@tonic-gate gettext("Couldn't read database_name\n\n")); 244*7c478bd9Sstevel@tonic-gate exit(1); 245*7c478bd9Sstevel@tonic-gate } 246*7c478bd9Sstevel@tonic-gate 247*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\nKerberos update log (%s.ulog)\n"), 248*7c478bd9Sstevel@tonic-gate params.dbname); 249*7c478bd9Sstevel@tonic-gate 250*7c478bd9Sstevel@tonic-gate if (ulog_map(context, ¶ms, FKPROPLOG)) { 251*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Unable to map log file " 252*7c478bd9Sstevel@tonic-gate "%s.ulog\n\n"), params.dbname); 253*7c478bd9Sstevel@tonic-gate exit(1); 254*7c478bd9Sstevel@tonic-gate } 255*7c478bd9Sstevel@tonic-gate 256*7c478bd9Sstevel@tonic-gate log_ctx = context->kdblog_context; 257*7c478bd9Sstevel@tonic-gate if (log_ctx) 258*7c478bd9Sstevel@tonic-gate ulog = log_ctx->ulog; 259*7c478bd9Sstevel@tonic-gate else { 260*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Unable to map log file " 261*7c478bd9Sstevel@tonic-gate "%s.ulog\n\n"), params.dbname); 262*7c478bd9Sstevel@tonic-gate exit(1); 263*7c478bd9Sstevel@tonic-gate } 264*7c478bd9Sstevel@tonic-gate 265*7c478bd9Sstevel@tonic-gate if (ulog->kdb_hmagic != KDB_HMAGIC) { 266*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 267*7c478bd9Sstevel@tonic-gate gettext("Corrupt header log, exiting\n\n")); 268*7c478bd9Sstevel@tonic-gate exit(1); 269*7c478bd9Sstevel@tonic-gate } 270*7c478bd9Sstevel@tonic-gate 271*7c478bd9Sstevel@tonic-gate (void) printf(gettext("Update log dump :\n")); 272*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\tLog version # : %u\n"), ulog->db_version_num); 273*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\tLog state : ")); 274*7c478bd9Sstevel@tonic-gate switch (ulog->kdb_state) { 275*7c478bd9Sstevel@tonic-gate case KDB_STABLE: 276*7c478bd9Sstevel@tonic-gate (void) printf(gettext("Stable\n")); 277*7c478bd9Sstevel@tonic-gate break; 278*7c478bd9Sstevel@tonic-gate case KDB_UNSTABLE: 279*7c478bd9Sstevel@tonic-gate (void) printf(gettext("Unstable\n")); 280*7c478bd9Sstevel@tonic-gate break; 281*7c478bd9Sstevel@tonic-gate case KDB_CORRUPT: 282*7c478bd9Sstevel@tonic-gate (void) printf(gettext("Corrupt\n")); 283*7c478bd9Sstevel@tonic-gate break; 284*7c478bd9Sstevel@tonic-gate default: 285*7c478bd9Sstevel@tonic-gate (void) printf(gettext("Unknown state: %d\n"), 286*7c478bd9Sstevel@tonic-gate ulog->kdb_state); 287*7c478bd9Sstevel@tonic-gate break; 288*7c478bd9Sstevel@tonic-gate } 289*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\tEntry block size : %u\n"), ulog->kdb_block); 290*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\tNumber of entries : %u\n"), ulog->kdb_num); 291*7c478bd9Sstevel@tonic-gate 292*7c478bd9Sstevel@tonic-gate if (ulog->kdb_last_sno == 0) 293*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\tLast serial # : None\n")); 294*7c478bd9Sstevel@tonic-gate else { 295*7c478bd9Sstevel@tonic-gate if (ulog->kdb_first_sno == 0) 296*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\tFirst serial # : None\n")); 297*7c478bd9Sstevel@tonic-gate else { 298*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\tFirst serial # : ")); 299*7c478bd9Sstevel@tonic-gate (void) printf("%u\n", ulog->kdb_first_sno); 300*7c478bd9Sstevel@tonic-gate } 301*7c478bd9Sstevel@tonic-gate 302*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\tLast serial # : ")); 303*7c478bd9Sstevel@tonic-gate (void) printf("%u\n", ulog->kdb_last_sno); 304*7c478bd9Sstevel@tonic-gate } 305*7c478bd9Sstevel@tonic-gate 306*7c478bd9Sstevel@tonic-gate if (ulog->kdb_last_time.seconds == 0L) { 307*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\tLast time stamp : None\n")); 308*7c478bd9Sstevel@tonic-gate } else { 309*7c478bd9Sstevel@tonic-gate if (ulog->kdb_first_time.seconds == 0L) 310*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\tFirst time stamp : None\n")); 311*7c478bd9Sstevel@tonic-gate else { 312*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\tFirst time stamp : %s"), 313*7c478bd9Sstevel@tonic-gate ctime((time_t *) 314*7c478bd9Sstevel@tonic-gate &(ulog->kdb_first_time.seconds))); 315*7c478bd9Sstevel@tonic-gate } 316*7c478bd9Sstevel@tonic-gate 317*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\tLast time stamp : %s\n"), 318*7c478bd9Sstevel@tonic-gate ctime((time_t *)&(ulog->kdb_last_time.seconds))); 319*7c478bd9Sstevel@tonic-gate } 320*7c478bd9Sstevel@tonic-gate 321*7c478bd9Sstevel@tonic-gate if ((!headeronly) && ulog->kdb_num) { 322*7c478bd9Sstevel@tonic-gate print_update(ulog, entry, verbose); 323*7c478bd9Sstevel@tonic-gate } 324*7c478bd9Sstevel@tonic-gate 325*7c478bd9Sstevel@tonic-gate (void) printf("\n"); 326*7c478bd9Sstevel@tonic-gate 327*7c478bd9Sstevel@tonic-gate return (0); 328*7c478bd9Sstevel@tonic-gate } 329