1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * Copyright (c) 1998 by Sun Microsystems, Inc. 3*7c478bd9Sstevel@tonic-gate * All rights reserved. 4*7c478bd9Sstevel@tonic-gate */ 5*7c478bd9Sstevel@tonic-gate 6*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 7*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 8*7c478bd9Sstevel@tonic-gate 9*7c478bd9Sstevel@tonic-gate /* 10*7c478bd9Sstevel@tonic-gate * Copyright (c) 1980 Regents of the University of California. 11*7c478bd9Sstevel@tonic-gate * All rights reserved. The Berkeley software License Agreement 12*7c478bd9Sstevel@tonic-gate * specifies the terms and conditions for redistribution. 13*7c478bd9Sstevel@tonic-gate */ 14*7c478bd9Sstevel@tonic-gate 15*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 16*7c478bd9Sstevel@tonic-gate 17*7c478bd9Sstevel@tonic-gate #include <errno.h> 18*7c478bd9Sstevel@tonic-gate #include "dump.h" 19*7c478bd9Sstevel@tonic-gate 20*7c478bd9Sstevel@tonic-gate static unsigned int timeout; /* current timeout */ 21*7c478bd9Sstevel@tonic-gate static char *attnmessage, *saveattn; /* attention message */ 22*7c478bd9Sstevel@tonic-gate 23*7c478bd9Sstevel@tonic-gate #ifdef __STDC__ 24*7c478bd9Sstevel@tonic-gate static void alarmcatch(); 25*7c478bd9Sstevel@tonic-gate static int idatesort(const void *, const void *); 26*7c478bd9Sstevel@tonic-gate #else /* !__STDC__ */ 27*7c478bd9Sstevel@tonic-gate static void alarmcatch(); 28*7c478bd9Sstevel@tonic-gate static int idatesort(); 29*7c478bd9Sstevel@tonic-gate #endif 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 32*7c478bd9Sstevel@tonic-gate extern int xflag; 33*7c478bd9Sstevel@tonic-gate #endif 34*7c478bd9Sstevel@tonic-gate 35*7c478bd9Sstevel@tonic-gate /* 36*7c478bd9Sstevel@tonic-gate * Query the operator; This fascist piece of code requires 37*7c478bd9Sstevel@tonic-gate * an exact response. 38*7c478bd9Sstevel@tonic-gate * It is intended to protect dump aborting by inquisitive 39*7c478bd9Sstevel@tonic-gate * people banging on the console terminal to see what is 40*7c478bd9Sstevel@tonic-gate * happening which might cause dump to croak, destroying 41*7c478bd9Sstevel@tonic-gate * a large number of hours of work. 42*7c478bd9Sstevel@tonic-gate * 43*7c478bd9Sstevel@tonic-gate * Every time += 2 minutes we reprint the message, alerting others 44*7c478bd9Sstevel@tonic-gate * that dump needs attention. 45*7c478bd9Sstevel@tonic-gate */ 46*7c478bd9Sstevel@tonic-gate int 47*7c478bd9Sstevel@tonic-gate query(question) 48*7c478bd9Sstevel@tonic-gate char *question; 49*7c478bd9Sstevel@tonic-gate { 50*7c478bd9Sstevel@tonic-gate int def = -1; 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate while (def == -1) 53*7c478bd9Sstevel@tonic-gate def = query_once(question, -1); 54*7c478bd9Sstevel@tonic-gate return (def); 55*7c478bd9Sstevel@tonic-gate } 56*7c478bd9Sstevel@tonic-gate 57*7c478bd9Sstevel@tonic-gate static int in_query_once; 58*7c478bd9Sstevel@tonic-gate static jmp_buf sjalarmbuf; 59*7c478bd9Sstevel@tonic-gate 60*7c478bd9Sstevel@tonic-gate /* real simple check-sum */ 61*7c478bd9Sstevel@tonic-gate static int 62*7c478bd9Sstevel@tonic-gate addem(s) 63*7c478bd9Sstevel@tonic-gate char *s; 64*7c478bd9Sstevel@tonic-gate { 65*7c478bd9Sstevel@tonic-gate int total = 0; 66*7c478bd9Sstevel@tonic-gate 67*7c478bd9Sstevel@tonic-gate if (s == (char *)NULL) 68*7c478bd9Sstevel@tonic-gate return (total); 69*7c478bd9Sstevel@tonic-gate while (*s) 70*7c478bd9Sstevel@tonic-gate total += *s++; 71*7c478bd9Sstevel@tonic-gate return (total); 72*7c478bd9Sstevel@tonic-gate } 73*7c478bd9Sstevel@tonic-gate 74*7c478bd9Sstevel@tonic-gate int 75*7c478bd9Sstevel@tonic-gate query_once(question, def) 76*7c478bd9Sstevel@tonic-gate char *question; 77*7c478bd9Sstevel@tonic-gate int def; 78*7c478bd9Sstevel@tonic-gate { 79*7c478bd9Sstevel@tonic-gate static char *lastmsg; 80*7c478bd9Sstevel@tonic-gate static int lastmsgsum; 81*7c478bd9Sstevel@tonic-gate int msgsum; 82*7c478bd9Sstevel@tonic-gate char replybuffer[BUFSIZ]; 83*7c478bd9Sstevel@tonic-gate int back; 84*7c478bd9Sstevel@tonic-gate time32_t timeclockstate; 85*7c478bd9Sstevel@tonic-gate pollfd_t pollset; 86*7c478bd9Sstevel@tonic-gate struct sigvec sv; 87*7c478bd9Sstevel@tonic-gate 88*7c478bd9Sstevel@tonic-gate /* special hook to flush timeout cache */ 89*7c478bd9Sstevel@tonic-gate if (question == NULL) { 90*7c478bd9Sstevel@tonic-gate lastmsg = (char *)NULL; 91*7c478bd9Sstevel@tonic-gate lastmsgsum = 0; 92*7c478bd9Sstevel@tonic-gate return (0); 93*7c478bd9Sstevel@tonic-gate } 94*7c478bd9Sstevel@tonic-gate 95*7c478bd9Sstevel@tonic-gate attnmessage = question; 96*7c478bd9Sstevel@tonic-gate /* 97*7c478bd9Sstevel@tonic-gate * Only reset the state if the message changed somehow 98*7c478bd9Sstevel@tonic-gate */ 99*7c478bd9Sstevel@tonic-gate msgsum = addem(question); 100*7c478bd9Sstevel@tonic-gate if (lastmsg != question || lastmsgsum != msgsum) { 101*7c478bd9Sstevel@tonic-gate timeout = 0; 102*7c478bd9Sstevel@tonic-gate if (telapsed && tstart_writing) 103*7c478bd9Sstevel@tonic-gate *telapsed += time((time_t *)0) - *tstart_writing; 104*7c478bd9Sstevel@tonic-gate lastmsg = question; 105*7c478bd9Sstevel@tonic-gate lastmsgsum = msgsum; 106*7c478bd9Sstevel@tonic-gate } 107*7c478bd9Sstevel@tonic-gate timeclockstate = timeclock((time_t)0); 108*7c478bd9Sstevel@tonic-gate if (setjmp(sjalarmbuf) != 0) { 109*7c478bd9Sstevel@tonic-gate if (def != -1) { 110*7c478bd9Sstevel@tonic-gate if (def) 111*7c478bd9Sstevel@tonic-gate msgtail(gettext("YES\n")); 112*7c478bd9Sstevel@tonic-gate else 113*7c478bd9Sstevel@tonic-gate msgtail(gettext("NO\n")); 114*7c478bd9Sstevel@tonic-gate } 115*7c478bd9Sstevel@tonic-gate back = def; 116*7c478bd9Sstevel@tonic-gate goto done; 117*7c478bd9Sstevel@tonic-gate } 118*7c478bd9Sstevel@tonic-gate alarmcatch(); 119*7c478bd9Sstevel@tonic-gate in_query_once = 1; 120*7c478bd9Sstevel@tonic-gate pollset.fd = -1; 121*7c478bd9Sstevel@tonic-gate pollset.events = 0; 122*7c478bd9Sstevel@tonic-gate pollset.revents = 0; 123*7c478bd9Sstevel@tonic-gate if (isatty(fileno(stdin))) { 124*7c478bd9Sstevel@tonic-gate pollset.fd = fileno(stdin); 125*7c478bd9Sstevel@tonic-gate pollset.events = POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND; 126*7c478bd9Sstevel@tonic-gate } else { 127*7c478bd9Sstevel@tonic-gate dumpabort(); 128*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 129*7c478bd9Sstevel@tonic-gate } 130*7c478bd9Sstevel@tonic-gate for (;;) { 131*7c478bd9Sstevel@tonic-gate if (poll(&pollset, 1, -1) < 0) { 132*7c478bd9Sstevel@tonic-gate if (errno == EINTR) 133*7c478bd9Sstevel@tonic-gate continue; 134*7c478bd9Sstevel@tonic-gate perror("poll(stdin)"); 135*7c478bd9Sstevel@tonic-gate dumpabort(); 136*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 137*7c478bd9Sstevel@tonic-gate } 138*7c478bd9Sstevel@tonic-gate if (pollset.revents == 0) 139*7c478bd9Sstevel@tonic-gate continue; /* sanity check */ 140*7c478bd9Sstevel@tonic-gate if (fgets(replybuffer, sizeof (replybuffer), stdin) == NULL) { 141*7c478bd9Sstevel@tonic-gate if (ferror(stdin)) { 142*7c478bd9Sstevel@tonic-gate clearerr(stdin); 143*7c478bd9Sstevel@tonic-gate continue; 144*7c478bd9Sstevel@tonic-gate } else { 145*7c478bd9Sstevel@tonic-gate dumpabort(); 146*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 147*7c478bd9Sstevel@tonic-gate } 148*7c478bd9Sstevel@tonic-gate } 149*7c478bd9Sstevel@tonic-gate timeout = 0; 150*7c478bd9Sstevel@tonic-gate if (strcasecmp(replybuffer, gettext("yes\n")) == 0) { 151*7c478bd9Sstevel@tonic-gate back = 1; 152*7c478bd9Sstevel@tonic-gate lastmsg = (char *)NULL; 153*7c478bd9Sstevel@tonic-gate lastmsgsum = 0; 154*7c478bd9Sstevel@tonic-gate goto done; 155*7c478bd9Sstevel@tonic-gate } else if (strcasecmp(replybuffer, gettext("no\n")) == 0) { 156*7c478bd9Sstevel@tonic-gate back = 0; 157*7c478bd9Sstevel@tonic-gate lastmsg = (char *)NULL; 158*7c478bd9Sstevel@tonic-gate lastmsgsum = 0; 159*7c478bd9Sstevel@tonic-gate goto done; 160*7c478bd9Sstevel@tonic-gate } else { 161*7c478bd9Sstevel@tonic-gate msg(gettext("\"yes\" or \"no\"?\n")); 162*7c478bd9Sstevel@tonic-gate in_query_once = 0; 163*7c478bd9Sstevel@tonic-gate alarmcatch(); 164*7c478bd9Sstevel@tonic-gate in_query_once = 1; 165*7c478bd9Sstevel@tonic-gate } 166*7c478bd9Sstevel@tonic-gate } 167*7c478bd9Sstevel@tonic-gate done: 168*7c478bd9Sstevel@tonic-gate /* 169*7c478bd9Sstevel@tonic-gate * Turn off the alarm, and reset the signal to trap out.. 170*7c478bd9Sstevel@tonic-gate */ 171*7c478bd9Sstevel@tonic-gate (void) alarm(0); 172*7c478bd9Sstevel@tonic-gate attnmessage = NULL; 173*7c478bd9Sstevel@tonic-gate sv.sv_handler = sigAbort; 174*7c478bd9Sstevel@tonic-gate sv.sv_flags = SA_RESTART; 175*7c478bd9Sstevel@tonic-gate (void) sigemptyset(&sv.sa_mask); 176*7c478bd9Sstevel@tonic-gate (void) sigvec(SIGALRM, &sv, (struct sigvec *)0); 177*7c478bd9Sstevel@tonic-gate if (tstart_writing) 178*7c478bd9Sstevel@tonic-gate (void) time(tstart_writing); 179*7c478bd9Sstevel@tonic-gate (void) timeclock(timeclockstate); 180*7c478bd9Sstevel@tonic-gate in_query_once = 0; 181*7c478bd9Sstevel@tonic-gate return (back); 182*7c478bd9Sstevel@tonic-gate } 183*7c478bd9Sstevel@tonic-gate /* 184*7c478bd9Sstevel@tonic-gate * Alert the console operator, and enable the alarm clock to 185*7c478bd9Sstevel@tonic-gate * sleep for time += 2 minutes in case nobody comes to satisfy dump 186*7c478bd9Sstevel@tonic-gate * If the alarm goes off while in the query_once for loop, we just 187*7c478bd9Sstevel@tonic-gate * longjmp back there and return the default answer. 188*7c478bd9Sstevel@tonic-gate */ 189*7c478bd9Sstevel@tonic-gate static void 190*7c478bd9Sstevel@tonic-gate #ifdef __STDC__ 191*7c478bd9Sstevel@tonic-gate alarmcatch(void) 192*7c478bd9Sstevel@tonic-gate #else 193*7c478bd9Sstevel@tonic-gate alarmcatch() 194*7c478bd9Sstevel@tonic-gate #endif 195*7c478bd9Sstevel@tonic-gate { 196*7c478bd9Sstevel@tonic-gate struct sigvec sv; 197*7c478bd9Sstevel@tonic-gate 198*7c478bd9Sstevel@tonic-gate if (in_query_once) { 199*7c478bd9Sstevel@tonic-gate longjmp(sjalarmbuf, 1); 200*7c478bd9Sstevel@tonic-gate } 201*7c478bd9Sstevel@tonic-gate if (timeout) { 202*7c478bd9Sstevel@tonic-gate msgtail("\n"); 203*7c478bd9Sstevel@tonic-gate } 204*7c478bd9Sstevel@tonic-gate 205*7c478bd9Sstevel@tonic-gate timeout += 120; 206*7c478bd9Sstevel@tonic-gate msg(gettext("NEEDS ATTENTION: %s"), attnmessage); 207*7c478bd9Sstevel@tonic-gate sv.sv_handler = alarmcatch; 208*7c478bd9Sstevel@tonic-gate sv.sv_flags = SA_RESTART; 209*7c478bd9Sstevel@tonic-gate (void) sigemptyset(&sv.sa_mask); 210*7c478bd9Sstevel@tonic-gate (void) sigvec(SIGALRM, &sv, (struct sigvec *)0); 211*7c478bd9Sstevel@tonic-gate (void) alarm(timeout); 212*7c478bd9Sstevel@tonic-gate } 213*7c478bd9Sstevel@tonic-gate 214*7c478bd9Sstevel@tonic-gate /* 215*7c478bd9Sstevel@tonic-gate * Here if an inquisitive operator interrupts the dump program 216*7c478bd9Sstevel@tonic-gate */ 217*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 218*7c478bd9Sstevel@tonic-gate void 219*7c478bd9Sstevel@tonic-gate interrupt(sig) 220*7c478bd9Sstevel@tonic-gate int sig; 221*7c478bd9Sstevel@tonic-gate { 222*7c478bd9Sstevel@tonic-gate if (!saveattn) { 223*7c478bd9Sstevel@tonic-gate saveattn = attnmessage; 224*7c478bd9Sstevel@tonic-gate } 225*7c478bd9Sstevel@tonic-gate msg(gettext("Interrupt received.\n")); 226*7c478bd9Sstevel@tonic-gate if (query(gettext( 227*7c478bd9Sstevel@tonic-gate "Do you want to abort dump?: (\"yes\" or \"no\") "))) { 228*7c478bd9Sstevel@tonic-gate dumpabort(); 229*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 230*7c478bd9Sstevel@tonic-gate } 231*7c478bd9Sstevel@tonic-gate if (saveattn) { 232*7c478bd9Sstevel@tonic-gate attnmessage = saveattn; 233*7c478bd9Sstevel@tonic-gate saveattn = NULL; 234*7c478bd9Sstevel@tonic-gate alarmcatch(); 235*7c478bd9Sstevel@tonic-gate } 236*7c478bd9Sstevel@tonic-gate } 237*7c478bd9Sstevel@tonic-gate 238*7c478bd9Sstevel@tonic-gate /* 239*7c478bd9Sstevel@tonic-gate * We use wall(1) to do the actual broadcasting, so 240*7c478bd9Sstevel@tonic-gate * that we don't have to worry about duplicated code 241*7c478bd9Sstevel@tonic-gate * only getting fixed in one place. This also saves 242*7c478bd9Sstevel@tonic-gate * us from having to worry about process groups, 243*7c478bd9Sstevel@tonic-gate * controlling terminals, and the like. 244*7c478bd9Sstevel@tonic-gate */ 245*7c478bd9Sstevel@tonic-gate void 246*7c478bd9Sstevel@tonic-gate broadcast(message) 247*7c478bd9Sstevel@tonic-gate char *message; 248*7c478bd9Sstevel@tonic-gate { 249*7c478bd9Sstevel@tonic-gate time_t clock; 250*7c478bd9Sstevel@tonic-gate pid_t pid; 251*7c478bd9Sstevel@tonic-gate int saverr; 252*7c478bd9Sstevel@tonic-gate int fildes[2]; 253*7c478bd9Sstevel@tonic-gate FILE *wall; 254*7c478bd9Sstevel@tonic-gate struct tm *localclock; 255*7c478bd9Sstevel@tonic-gate 256*7c478bd9Sstevel@tonic-gate if (!notify) 257*7c478bd9Sstevel@tonic-gate return; 258*7c478bd9Sstevel@tonic-gate 259*7c478bd9Sstevel@tonic-gate if (pipe(fildes) < 0) { 260*7c478bd9Sstevel@tonic-gate saverr = errno; 261*7c478bd9Sstevel@tonic-gate msg(gettext("pipe: %s\n"), strerror(saverr)); 262*7c478bd9Sstevel@tonic-gate return; 263*7c478bd9Sstevel@tonic-gate } 264*7c478bd9Sstevel@tonic-gate 265*7c478bd9Sstevel@tonic-gate switch (pid = fork()) { 266*7c478bd9Sstevel@tonic-gate case -1: 267*7c478bd9Sstevel@tonic-gate return; 268*7c478bd9Sstevel@tonic-gate case 0: 269*7c478bd9Sstevel@tonic-gate close(fildes[0]); 270*7c478bd9Sstevel@tonic-gate if (dup2(fildes[1], 0) < 0) { 271*7c478bd9Sstevel@tonic-gate saverr = errno; 272*7c478bd9Sstevel@tonic-gate msg(gettext("dup2: %s\n"), strerror(saverr)); 273*7c478bd9Sstevel@tonic-gate exit(1); 274*7c478bd9Sstevel@tonic-gate } 275*7c478bd9Sstevel@tonic-gate execl("/usr/sbin/wall", "wall", "-g", OPGRENT, (char *)NULL); 276*7c478bd9Sstevel@tonic-gate saverr = errno; 277*7c478bd9Sstevel@tonic-gate msg(gettext("execl: %s\n"), strerror(saverr)); 278*7c478bd9Sstevel@tonic-gate exit(1); 279*7c478bd9Sstevel@tonic-gate default: 280*7c478bd9Sstevel@tonic-gate break; /* parent */ 281*7c478bd9Sstevel@tonic-gate } 282*7c478bd9Sstevel@tonic-gate 283*7c478bd9Sstevel@tonic-gate close(fildes[1]); 284*7c478bd9Sstevel@tonic-gate wall = fdopen(fildes[0], "r+"); 285*7c478bd9Sstevel@tonic-gate if (wall == (FILE *)NULL) { 286*7c478bd9Sstevel@tonic-gate saverr = errno; 287*7c478bd9Sstevel@tonic-gate msg(gettext("fdopen: %s\n"), strerror(saverr)); 288*7c478bd9Sstevel@tonic-gate return; 289*7c478bd9Sstevel@tonic-gate } 290*7c478bd9Sstevel@tonic-gate 291*7c478bd9Sstevel@tonic-gate clock = time((time_t *)0); 292*7c478bd9Sstevel@tonic-gate localclock = localtime(&clock); 293*7c478bd9Sstevel@tonic-gate 294*7c478bd9Sstevel@tonic-gate (void) fprintf(wall, gettext( 295*7c478bd9Sstevel@tonic-gate "\n\007\007\007Message from the dump program to all operators at \ 296*7c478bd9Sstevel@tonic-gate %d:%02d ...\n\n%s"), 297*7c478bd9Sstevel@tonic-gate localclock->tm_hour, localclock->tm_min, message); 298*7c478bd9Sstevel@tonic-gate fclose(wall); 299*7c478bd9Sstevel@tonic-gate 300*7c478bd9Sstevel@tonic-gate while (wait((int *)0) != pid) { 301*7c478bd9Sstevel@tonic-gate continue; 302*7c478bd9Sstevel@tonic-gate /*LINTED [empty loop body]*/ 303*7c478bd9Sstevel@tonic-gate } 304*7c478bd9Sstevel@tonic-gate } 305*7c478bd9Sstevel@tonic-gate 306*7c478bd9Sstevel@tonic-gate /* 307*7c478bd9Sstevel@tonic-gate * print out an estimate of the amount of time left to do the dump 308*7c478bd9Sstevel@tonic-gate */ 309*7c478bd9Sstevel@tonic-gate #define EST_SEC 600 /* every 10 minutes */ 310*7c478bd9Sstevel@tonic-gate void 311*7c478bd9Sstevel@tonic-gate timeest(force, blkswritten) 312*7c478bd9Sstevel@tonic-gate int force; 313*7c478bd9Sstevel@tonic-gate int blkswritten; 314*7c478bd9Sstevel@tonic-gate { 315*7c478bd9Sstevel@tonic-gate time_t tnow, deltat; 316*7c478bd9Sstevel@tonic-gate char *msgp; 317*7c478bd9Sstevel@tonic-gate 318*7c478bd9Sstevel@tonic-gate if (tschedule == NULL) 319*7c478bd9Sstevel@tonic-gate return; 320*7c478bd9Sstevel@tonic-gate if (*tschedule == 0) 321*7c478bd9Sstevel@tonic-gate *tschedule = time((time_t *)0) + EST_SEC; 322*7c478bd9Sstevel@tonic-gate (void) time(&tnow); 323*7c478bd9Sstevel@tonic-gate if ((force || tnow >= *tschedule) && blkswritten) { 324*7c478bd9Sstevel@tonic-gate *tschedule = tnow + EST_SEC; 325*7c478bd9Sstevel@tonic-gate if (!force && blkswritten < 50 * ntrec) 326*7c478bd9Sstevel@tonic-gate return; 327*7c478bd9Sstevel@tonic-gate deltat = (*telapsed + (tnow - *tstart_writing)) 328*7c478bd9Sstevel@tonic-gate * ((double)esize / blkswritten - 1.0); 329*7c478bd9Sstevel@tonic-gate msgp = gettext("%3.2f%% done, finished in %d:%02d\n"); 330*7c478bd9Sstevel@tonic-gate msg(msgp, (blkswritten*100.0)/esize, 331*7c478bd9Sstevel@tonic-gate deltat/3600, (deltat%3600)/60); 332*7c478bd9Sstevel@tonic-gate } 333*7c478bd9Sstevel@tonic-gate } 334*7c478bd9Sstevel@tonic-gate 335*7c478bd9Sstevel@tonic-gate #include <stdarg.h> 336*7c478bd9Sstevel@tonic-gate 337*7c478bd9Sstevel@tonic-gate /* VARARGS1 */ 338*7c478bd9Sstevel@tonic-gate void 339*7c478bd9Sstevel@tonic-gate msg(const char *fmt, ...) 340*7c478bd9Sstevel@tonic-gate { 341*7c478bd9Sstevel@tonic-gate char buf[1024], *cp; 342*7c478bd9Sstevel@tonic-gate size_t size; 343*7c478bd9Sstevel@tonic-gate va_list args; 344*7c478bd9Sstevel@tonic-gate 345*7c478bd9Sstevel@tonic-gate va_start(args, fmt); 346*7c478bd9Sstevel@tonic-gate (void) strcpy(buf, " DUMP: "); 347*7c478bd9Sstevel@tonic-gate cp = &buf[strlen(buf)]; 348*7c478bd9Sstevel@tonic-gate #ifdef TDEBUG 349*7c478bd9Sstevel@tonic-gate (void) sprintf(cp, "pid=%d ", getpid()); 350*7c478bd9Sstevel@tonic-gate cp = &buf[strlen(buf)]; 351*7c478bd9Sstevel@tonic-gate #endif 352*7c478bd9Sstevel@tonic-gate /* don't need -1, vsnprintf does it right */ 353*7c478bd9Sstevel@tonic-gate /* LINTED pointer arithmetic result fits in size_t */ 354*7c478bd9Sstevel@tonic-gate size = ((size_t)sizeof (buf)) - (size_t)(cp - buf); 355*7c478bd9Sstevel@tonic-gate (void) vsnprintf(cp, size, fmt, args); 356*7c478bd9Sstevel@tonic-gate (void) fputs(buf, stderr); 357*7c478bd9Sstevel@tonic-gate (void) fflush(stdout); 358*7c478bd9Sstevel@tonic-gate (void) fflush(stderr); 359*7c478bd9Sstevel@tonic-gate va_end(args); 360*7c478bd9Sstevel@tonic-gate } 361*7c478bd9Sstevel@tonic-gate 362*7c478bd9Sstevel@tonic-gate /* VARARGS1 */ 363*7c478bd9Sstevel@tonic-gate void 364*7c478bd9Sstevel@tonic-gate msgtail(const char *fmt, ...) 365*7c478bd9Sstevel@tonic-gate { 366*7c478bd9Sstevel@tonic-gate va_list args; 367*7c478bd9Sstevel@tonic-gate 368*7c478bd9Sstevel@tonic-gate va_start(args, fmt); 369*7c478bd9Sstevel@tonic-gate (void) vfprintf(stderr, fmt, args); 370*7c478bd9Sstevel@tonic-gate va_end(args); 371*7c478bd9Sstevel@tonic-gate } 372*7c478bd9Sstevel@tonic-gate 373*7c478bd9Sstevel@tonic-gate #define MINUTES(x) ((x) * 60) 374*7c478bd9Sstevel@tonic-gate 375*7c478bd9Sstevel@tonic-gate /* 376*7c478bd9Sstevel@tonic-gate * Tell the operator what has to be done; 377*7c478bd9Sstevel@tonic-gate * we don't actually do it 378*7c478bd9Sstevel@tonic-gate */ 379*7c478bd9Sstevel@tonic-gate void 380*7c478bd9Sstevel@tonic-gate lastdump(arg) /* w ==> just what to do; W ==> most recent dumps */ 381*7c478bd9Sstevel@tonic-gate int arg; 382*7c478bd9Sstevel@tonic-gate { 383*7c478bd9Sstevel@tonic-gate char *lastname; 384*7c478bd9Sstevel@tonic-gate char *date; 385*7c478bd9Sstevel@tonic-gate int i; 386*7c478bd9Sstevel@tonic-gate time_t tnow, ddate; 387*7c478bd9Sstevel@tonic-gate struct mntent *dt; 388*7c478bd9Sstevel@tonic-gate int dumpme = 0; 389*7c478bd9Sstevel@tonic-gate struct idates *itwalk; 390*7c478bd9Sstevel@tonic-gate 391*7c478bd9Sstevel@tonic-gate (void) time(&tnow); 392*7c478bd9Sstevel@tonic-gate mnttabread(); /* /etc/fstab input */ 393*7c478bd9Sstevel@tonic-gate inititimes(); /* /etc/dumpdates input */ 394*7c478bd9Sstevel@tonic-gate 395*7c478bd9Sstevel@tonic-gate /* Don't use msg(), this isn't a tell-the-world kind of thing */ 396*7c478bd9Sstevel@tonic-gate if (arg == 'w') 397*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, gettext("Dump these file systems:\n")); 398*7c478bd9Sstevel@tonic-gate else 399*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, gettext( 400*7c478bd9Sstevel@tonic-gate "Last dump(s) done (Dump '>' file systems):\n")); 401*7c478bd9Sstevel@tonic-gate 402*7c478bd9Sstevel@tonic-gate if (idatev != NULL) { 403*7c478bd9Sstevel@tonic-gate qsort((char *)idatev, nidates, sizeof (*idatev), idatesort); 404*7c478bd9Sstevel@tonic-gate lastname = "??"; 405*7c478bd9Sstevel@tonic-gate ITITERATE(i, itwalk) { 406*7c478bd9Sstevel@tonic-gate if (strncmp(lastname, itwalk->id_name, 407*7c478bd9Sstevel@tonic-gate sizeof (itwalk->id_name)) == 0) 408*7c478bd9Sstevel@tonic-gate continue; 409*7c478bd9Sstevel@tonic-gate /* must be ctime(), per ufsdump(4) */ 410*7c478bd9Sstevel@tonic-gate ddate = itwalk->id_ddate; 411*7c478bd9Sstevel@tonic-gate date = (char *)ctime(&ddate); 412*7c478bd9Sstevel@tonic-gate date[16] = '\0'; /* blow away seconds and year */ 413*7c478bd9Sstevel@tonic-gate lastname = itwalk->id_name; 414*7c478bd9Sstevel@tonic-gate dt = mnttabsearch(itwalk->id_name, 0); 415*7c478bd9Sstevel@tonic-gate if ((time_t)(itwalk->id_ddate) < (tnow - DAY)) { 416*7c478bd9Sstevel@tonic-gate dumpme = 1; 417*7c478bd9Sstevel@tonic-gate } 418*7c478bd9Sstevel@tonic-gate 419*7c478bd9Sstevel@tonic-gate if ((arg == 'w') && dumpme) { 420*7c478bd9Sstevel@tonic-gate /* 421*7c478bd9Sstevel@tonic-gate * Handle the w option: print out file systems 422*7c478bd9Sstevel@tonic-gate * which haven't been backed up within a day. 423*7c478bd9Sstevel@tonic-gate */ 424*7c478bd9Sstevel@tonic-gate (void) printf(gettext("%8s\t(%6s)\n"), 425*7c478bd9Sstevel@tonic-gate itwalk->id_name, dt ? dt->mnt_dir : ""); 426*7c478bd9Sstevel@tonic-gate } 427*7c478bd9Sstevel@tonic-gate if (arg == 'W') { 428*7c478bd9Sstevel@tonic-gate /* 429*7c478bd9Sstevel@tonic-gate * Handle the W option: print out ALL 430*7c478bd9Sstevel@tonic-gate * filesystems including recent dump dates and 431*7c478bd9Sstevel@tonic-gate * dump levels. Mark the backup-needing 432*7c478bd9Sstevel@tonic-gate * filesystems with a >. 433*7c478bd9Sstevel@tonic-gate */ 434*7c478bd9Sstevel@tonic-gate (void) printf(gettext( 435*7c478bd9Sstevel@tonic-gate "%c %8s\t(%6s) Last dump: Level %c, Date %s\n"), 436*7c478bd9Sstevel@tonic-gate dumpme ? '>' : ' ', 437*7c478bd9Sstevel@tonic-gate itwalk->id_name, 438*7c478bd9Sstevel@tonic-gate dt ? dt->mnt_dir : "", 439*7c478bd9Sstevel@tonic-gate (uchar_t)itwalk->id_incno, 440*7c478bd9Sstevel@tonic-gate date); 441*7c478bd9Sstevel@tonic-gate } 442*7c478bd9Sstevel@tonic-gate dumpme = 0; 443*7c478bd9Sstevel@tonic-gate } 444*7c478bd9Sstevel@tonic-gate } 445*7c478bd9Sstevel@tonic-gate } 446*7c478bd9Sstevel@tonic-gate 447*7c478bd9Sstevel@tonic-gate static int 448*7c478bd9Sstevel@tonic-gate idatesort(v1, v2) 449*7c478bd9Sstevel@tonic-gate #ifdef __STDC__ 450*7c478bd9Sstevel@tonic-gate const void *v1; 451*7c478bd9Sstevel@tonic-gate const void *v2; 452*7c478bd9Sstevel@tonic-gate #else 453*7c478bd9Sstevel@tonic-gate void *v1; 454*7c478bd9Sstevel@tonic-gate void *v2; 455*7c478bd9Sstevel@tonic-gate #endif 456*7c478bd9Sstevel@tonic-gate { 457*7c478bd9Sstevel@tonic-gate struct idates **p1 = (struct idates **)v1; 458*7c478bd9Sstevel@tonic-gate struct idates **p2 = (struct idates **)v2; 459*7c478bd9Sstevel@tonic-gate int diff; 460*7c478bd9Sstevel@tonic-gate 461*7c478bd9Sstevel@tonic-gate diff = strcoll((*p1)->id_name, (*p2)->id_name); 462*7c478bd9Sstevel@tonic-gate if (diff == 0) { 463*7c478bd9Sstevel@tonic-gate /* 464*7c478bd9Sstevel@tonic-gate * Time may eventually become unsigned, so can't 465*7c478bd9Sstevel@tonic-gate * rely on subtraction to give a useful result. 466*7c478bd9Sstevel@tonic-gate * Note that we are sorting dates into reverse 467*7c478bd9Sstevel@tonic-gate * order, so that we will report based on the 468*7c478bd9Sstevel@tonic-gate * most-recent record for a particular filesystem. 469*7c478bd9Sstevel@tonic-gate */ 470*7c478bd9Sstevel@tonic-gate if ((*p1)->id_ddate > (*p2)->id_ddate) 471*7c478bd9Sstevel@tonic-gate diff = -1; 472*7c478bd9Sstevel@tonic-gate else if ((*p1)->id_ddate < (*p2)->id_ddate) 473*7c478bd9Sstevel@tonic-gate diff = 1; 474*7c478bd9Sstevel@tonic-gate } 475*7c478bd9Sstevel@tonic-gate return (diff); 476*7c478bd9Sstevel@tonic-gate } 477