17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * Copyright (c) 1998 by Sun Microsystems, Inc.
37c478bd9Sstevel@tonic-gate * All rights reserved.
47c478bd9Sstevel@tonic-gate */
57c478bd9Sstevel@tonic-gate
67c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
77c478bd9Sstevel@tonic-gate /* All Rights Reserved */
87c478bd9Sstevel@tonic-gate
97c478bd9Sstevel@tonic-gate /*
107c478bd9Sstevel@tonic-gate * Copyright (c) 1980 Regents of the University of California.
117c478bd9Sstevel@tonic-gate * All rights reserved. The Berkeley software License Agreement
127c478bd9Sstevel@tonic-gate * specifies the terms and conditions for redistribution.
137c478bd9Sstevel@tonic-gate */
147c478bd9Sstevel@tonic-gate
157c478bd9Sstevel@tonic-gate #include <errno.h>
167c478bd9Sstevel@tonic-gate #include "dump.h"
177c478bd9Sstevel@tonic-gate
18e0dfa398SToomas Soome time_t *tschedule;
197c478bd9Sstevel@tonic-gate static unsigned int timeout; /* current timeout */
207c478bd9Sstevel@tonic-gate static char *attnmessage, *saveattn; /* attention message */
217c478bd9Sstevel@tonic-gate
22*30699046SRichard Lowe static void alarmcatch(int);
237c478bd9Sstevel@tonic-gate static int idatesort(const void *, const void *);
247c478bd9Sstevel@tonic-gate
257c478bd9Sstevel@tonic-gate #ifdef DEBUG
267c478bd9Sstevel@tonic-gate extern int xflag;
277c478bd9Sstevel@tonic-gate #endif
287c478bd9Sstevel@tonic-gate
297c478bd9Sstevel@tonic-gate /*
307c478bd9Sstevel@tonic-gate * Query the operator; This fascist piece of code requires
317c478bd9Sstevel@tonic-gate * an exact response.
327c478bd9Sstevel@tonic-gate * It is intended to protect dump aborting by inquisitive
337c478bd9Sstevel@tonic-gate * people banging on the console terminal to see what is
347c478bd9Sstevel@tonic-gate * happening which might cause dump to croak, destroying
357c478bd9Sstevel@tonic-gate * a large number of hours of work.
367c478bd9Sstevel@tonic-gate *
377c478bd9Sstevel@tonic-gate * Every time += 2 minutes we reprint the message, alerting others
387c478bd9Sstevel@tonic-gate * that dump needs attention.
397c478bd9Sstevel@tonic-gate */
407c478bd9Sstevel@tonic-gate int
query(char * question)41e0dfa398SToomas Soome query(char *question)
427c478bd9Sstevel@tonic-gate {
437c478bd9Sstevel@tonic-gate int def = -1;
447c478bd9Sstevel@tonic-gate
457c478bd9Sstevel@tonic-gate while (def == -1)
467c478bd9Sstevel@tonic-gate def = query_once(question, -1);
477c478bd9Sstevel@tonic-gate return (def);
487c478bd9Sstevel@tonic-gate }
497c478bd9Sstevel@tonic-gate
507c478bd9Sstevel@tonic-gate static int in_query_once;
517c478bd9Sstevel@tonic-gate static jmp_buf sjalarmbuf;
527c478bd9Sstevel@tonic-gate
537c478bd9Sstevel@tonic-gate /* real simple check-sum */
547c478bd9Sstevel@tonic-gate static int
addem(char * s)55e0dfa398SToomas Soome addem(char *s)
567c478bd9Sstevel@tonic-gate {
577c478bd9Sstevel@tonic-gate int total = 0;
587c478bd9Sstevel@tonic-gate
597c478bd9Sstevel@tonic-gate if (s == (char *)NULL)
607c478bd9Sstevel@tonic-gate return (total);
617c478bd9Sstevel@tonic-gate while (*s)
627c478bd9Sstevel@tonic-gate total += *s++;
637c478bd9Sstevel@tonic-gate return (total);
647c478bd9Sstevel@tonic-gate }
657c478bd9Sstevel@tonic-gate
667c478bd9Sstevel@tonic-gate int
query_once(char * question,int def)67e0dfa398SToomas Soome query_once(char *question, int def)
687c478bd9Sstevel@tonic-gate {
697c478bd9Sstevel@tonic-gate static char *lastmsg;
707c478bd9Sstevel@tonic-gate static int lastmsgsum;
717c478bd9Sstevel@tonic-gate int msgsum;
727c478bd9Sstevel@tonic-gate char replybuffer[BUFSIZ];
737c478bd9Sstevel@tonic-gate int back;
747c478bd9Sstevel@tonic-gate time32_t timeclockstate;
757c478bd9Sstevel@tonic-gate pollfd_t pollset;
767c478bd9Sstevel@tonic-gate struct sigvec sv;
777c478bd9Sstevel@tonic-gate
787c478bd9Sstevel@tonic-gate /* special hook to flush timeout cache */
797c478bd9Sstevel@tonic-gate if (question == NULL) {
807c478bd9Sstevel@tonic-gate lastmsg = (char *)NULL;
817c478bd9Sstevel@tonic-gate lastmsgsum = 0;
827c478bd9Sstevel@tonic-gate return (0);
837c478bd9Sstevel@tonic-gate }
847c478bd9Sstevel@tonic-gate
857c478bd9Sstevel@tonic-gate attnmessage = question;
867c478bd9Sstevel@tonic-gate /*
877c478bd9Sstevel@tonic-gate * Only reset the state if the message changed somehow
887c478bd9Sstevel@tonic-gate */
897c478bd9Sstevel@tonic-gate msgsum = addem(question);
907c478bd9Sstevel@tonic-gate if (lastmsg != question || lastmsgsum != msgsum) {
917c478bd9Sstevel@tonic-gate timeout = 0;
927c478bd9Sstevel@tonic-gate if (telapsed && tstart_writing)
937c478bd9Sstevel@tonic-gate *telapsed += time((time_t *)0) - *tstart_writing;
947c478bd9Sstevel@tonic-gate lastmsg = question;
957c478bd9Sstevel@tonic-gate lastmsgsum = msgsum;
967c478bd9Sstevel@tonic-gate }
977c478bd9Sstevel@tonic-gate timeclockstate = timeclock((time_t)0);
987c478bd9Sstevel@tonic-gate if (setjmp(sjalarmbuf) != 0) {
997c478bd9Sstevel@tonic-gate if (def != -1) {
1007c478bd9Sstevel@tonic-gate if (def)
1017c478bd9Sstevel@tonic-gate msgtail(gettext("YES\n"));
1027c478bd9Sstevel@tonic-gate else
1037c478bd9Sstevel@tonic-gate msgtail(gettext("NO\n"));
1047c478bd9Sstevel@tonic-gate }
1057c478bd9Sstevel@tonic-gate back = def;
1067c478bd9Sstevel@tonic-gate goto done;
1077c478bd9Sstevel@tonic-gate }
108*30699046SRichard Lowe alarmcatch(SIGALRM);
1097c478bd9Sstevel@tonic-gate in_query_once = 1;
1107c478bd9Sstevel@tonic-gate pollset.fd = -1;
1117c478bd9Sstevel@tonic-gate pollset.events = 0;
1127c478bd9Sstevel@tonic-gate pollset.revents = 0;
1137c478bd9Sstevel@tonic-gate if (isatty(fileno(stdin))) {
1147c478bd9Sstevel@tonic-gate pollset.fd = fileno(stdin);
1157c478bd9Sstevel@tonic-gate pollset.events = POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND;
1167c478bd9Sstevel@tonic-gate } else {
1177c478bd9Sstevel@tonic-gate dumpabort();
1187c478bd9Sstevel@tonic-gate /*NOTREACHED*/
1197c478bd9Sstevel@tonic-gate }
1207c478bd9Sstevel@tonic-gate for (;;) {
1217c478bd9Sstevel@tonic-gate if (poll(&pollset, 1, -1) < 0) {
1227c478bd9Sstevel@tonic-gate if (errno == EINTR)
1237c478bd9Sstevel@tonic-gate continue;
1247c478bd9Sstevel@tonic-gate perror("poll(stdin)");
1257c478bd9Sstevel@tonic-gate dumpabort();
1267c478bd9Sstevel@tonic-gate /*NOTREACHED*/
1277c478bd9Sstevel@tonic-gate }
1287c478bd9Sstevel@tonic-gate if (pollset.revents == 0)
1297c478bd9Sstevel@tonic-gate continue; /* sanity check */
1307c478bd9Sstevel@tonic-gate if (fgets(replybuffer, sizeof (replybuffer), stdin) == NULL) {
1317c478bd9Sstevel@tonic-gate if (ferror(stdin)) {
1327c478bd9Sstevel@tonic-gate clearerr(stdin);
1337c478bd9Sstevel@tonic-gate continue;
1347c478bd9Sstevel@tonic-gate } else {
1357c478bd9Sstevel@tonic-gate dumpabort();
1367c478bd9Sstevel@tonic-gate /*NOTREACHED*/
1377c478bd9Sstevel@tonic-gate }
1387c478bd9Sstevel@tonic-gate }
1397c478bd9Sstevel@tonic-gate timeout = 0;
1407c478bd9Sstevel@tonic-gate if (strcasecmp(replybuffer, gettext("yes\n")) == 0) {
1417c478bd9Sstevel@tonic-gate back = 1;
1427c478bd9Sstevel@tonic-gate lastmsg = (char *)NULL;
1437c478bd9Sstevel@tonic-gate lastmsgsum = 0;
1447c478bd9Sstevel@tonic-gate goto done;
1457c478bd9Sstevel@tonic-gate } else if (strcasecmp(replybuffer, gettext("no\n")) == 0) {
1467c478bd9Sstevel@tonic-gate back = 0;
1477c478bd9Sstevel@tonic-gate lastmsg = (char *)NULL;
1487c478bd9Sstevel@tonic-gate lastmsgsum = 0;
1497c478bd9Sstevel@tonic-gate goto done;
1507c478bd9Sstevel@tonic-gate } else {
1517c478bd9Sstevel@tonic-gate msg(gettext("\"yes\" or \"no\"?\n"));
1527c478bd9Sstevel@tonic-gate in_query_once = 0;
153*30699046SRichard Lowe alarmcatch(SIGALRM);
1547c478bd9Sstevel@tonic-gate in_query_once = 1;
1557c478bd9Sstevel@tonic-gate }
1567c478bd9Sstevel@tonic-gate }
1577c478bd9Sstevel@tonic-gate done:
1587c478bd9Sstevel@tonic-gate /*
1597c478bd9Sstevel@tonic-gate * Turn off the alarm, and reset the signal to trap out..
1607c478bd9Sstevel@tonic-gate */
1617c478bd9Sstevel@tonic-gate (void) alarm(0);
1627c478bd9Sstevel@tonic-gate attnmessage = NULL;
1637c478bd9Sstevel@tonic-gate sv.sv_handler = sigAbort;
1647c478bd9Sstevel@tonic-gate sv.sv_flags = SA_RESTART;
1657c478bd9Sstevel@tonic-gate (void) sigemptyset(&sv.sa_mask);
1667c478bd9Sstevel@tonic-gate (void) sigvec(SIGALRM, &sv, (struct sigvec *)0);
1677c478bd9Sstevel@tonic-gate if (tstart_writing)
1687c478bd9Sstevel@tonic-gate (void) time(tstart_writing);
1697c478bd9Sstevel@tonic-gate (void) timeclock(timeclockstate);
1707c478bd9Sstevel@tonic-gate in_query_once = 0;
1717c478bd9Sstevel@tonic-gate return (back);
1727c478bd9Sstevel@tonic-gate }
1737c478bd9Sstevel@tonic-gate /*
1747c478bd9Sstevel@tonic-gate * Alert the console operator, and enable the alarm clock to
1757c478bd9Sstevel@tonic-gate * sleep for time += 2 minutes in case nobody comes to satisfy dump
1767c478bd9Sstevel@tonic-gate * If the alarm goes off while in the query_once for loop, we just
1777c478bd9Sstevel@tonic-gate * longjmp back there and return the default answer.
1787c478bd9Sstevel@tonic-gate */
1797c478bd9Sstevel@tonic-gate static void
alarmcatch(int signal __unused)180*30699046SRichard Lowe alarmcatch(int signal __unused)
1817c478bd9Sstevel@tonic-gate {
1827c478bd9Sstevel@tonic-gate struct sigvec sv;
1837c478bd9Sstevel@tonic-gate
1847c478bd9Sstevel@tonic-gate if (in_query_once) {
1857c478bd9Sstevel@tonic-gate longjmp(sjalarmbuf, 1);
1867c478bd9Sstevel@tonic-gate }
1877c478bd9Sstevel@tonic-gate if (timeout) {
1887c478bd9Sstevel@tonic-gate msgtail("\n");
1897c478bd9Sstevel@tonic-gate }
1907c478bd9Sstevel@tonic-gate
1917c478bd9Sstevel@tonic-gate timeout += 120;
1927c478bd9Sstevel@tonic-gate msg(gettext("NEEDS ATTENTION: %s"), attnmessage);
1937c478bd9Sstevel@tonic-gate sv.sv_handler = alarmcatch;
1947c478bd9Sstevel@tonic-gate sv.sv_flags = SA_RESTART;
1957c478bd9Sstevel@tonic-gate (void) sigemptyset(&sv.sa_mask);
1967c478bd9Sstevel@tonic-gate (void) sigvec(SIGALRM, &sv, (struct sigvec *)0);
1977c478bd9Sstevel@tonic-gate (void) alarm(timeout);
1987c478bd9Sstevel@tonic-gate }
1997c478bd9Sstevel@tonic-gate
2007c478bd9Sstevel@tonic-gate /*
2017c478bd9Sstevel@tonic-gate * Here if an inquisitive operator interrupts the dump program
2027c478bd9Sstevel@tonic-gate */
2037c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2047c478bd9Sstevel@tonic-gate void
interrupt(int sig)205e0dfa398SToomas Soome interrupt(int sig)
2067c478bd9Sstevel@tonic-gate {
2077c478bd9Sstevel@tonic-gate if (!saveattn) {
2087c478bd9Sstevel@tonic-gate saveattn = attnmessage;
2097c478bd9Sstevel@tonic-gate }
2107c478bd9Sstevel@tonic-gate msg(gettext("Interrupt received.\n"));
2117c478bd9Sstevel@tonic-gate if (query(gettext(
2127c478bd9Sstevel@tonic-gate "Do you want to abort dump?: (\"yes\" or \"no\") "))) {
2137c478bd9Sstevel@tonic-gate dumpabort();
2147c478bd9Sstevel@tonic-gate /*NOTREACHED*/
2157c478bd9Sstevel@tonic-gate }
2167c478bd9Sstevel@tonic-gate if (saveattn) {
2177c478bd9Sstevel@tonic-gate attnmessage = saveattn;
2187c478bd9Sstevel@tonic-gate saveattn = NULL;
219*30699046SRichard Lowe alarmcatch(SIGALRM);
2207c478bd9Sstevel@tonic-gate }
2217c478bd9Sstevel@tonic-gate }
2227c478bd9Sstevel@tonic-gate
2237c478bd9Sstevel@tonic-gate /*
2247c478bd9Sstevel@tonic-gate * We use wall(1) to do the actual broadcasting, so
2257c478bd9Sstevel@tonic-gate * that we don't have to worry about duplicated code
2267c478bd9Sstevel@tonic-gate * only getting fixed in one place. This also saves
2277c478bd9Sstevel@tonic-gate * us from having to worry about process groups,
2287c478bd9Sstevel@tonic-gate * controlling terminals, and the like.
2297c478bd9Sstevel@tonic-gate */
2307c478bd9Sstevel@tonic-gate void
broadcast(char * message)231e0dfa398SToomas Soome broadcast(char *message)
2327c478bd9Sstevel@tonic-gate {
2337c478bd9Sstevel@tonic-gate time_t clock;
2347c478bd9Sstevel@tonic-gate pid_t pid;
2357c478bd9Sstevel@tonic-gate int saverr;
2367c478bd9Sstevel@tonic-gate int fildes[2];
2377c478bd9Sstevel@tonic-gate FILE *wall;
2387c478bd9Sstevel@tonic-gate struct tm *localclock;
2397c478bd9Sstevel@tonic-gate
2407c478bd9Sstevel@tonic-gate if (!notify)
2417c478bd9Sstevel@tonic-gate return;
2427c478bd9Sstevel@tonic-gate
2437c478bd9Sstevel@tonic-gate if (pipe(fildes) < 0) {
2447c478bd9Sstevel@tonic-gate saverr = errno;
2457c478bd9Sstevel@tonic-gate msg(gettext("pipe: %s\n"), strerror(saverr));
2467c478bd9Sstevel@tonic-gate return;
2477c478bd9Sstevel@tonic-gate }
2487c478bd9Sstevel@tonic-gate
2497c478bd9Sstevel@tonic-gate switch (pid = fork()) {
2507c478bd9Sstevel@tonic-gate case -1:
2517c478bd9Sstevel@tonic-gate return;
2527c478bd9Sstevel@tonic-gate case 0:
2537c478bd9Sstevel@tonic-gate close(fildes[0]);
2547c478bd9Sstevel@tonic-gate if (dup2(fildes[1], 0) < 0) {
2557c478bd9Sstevel@tonic-gate saverr = errno;
2567c478bd9Sstevel@tonic-gate msg(gettext("dup2: %s\n"), strerror(saverr));
2577c478bd9Sstevel@tonic-gate exit(1);
2587c478bd9Sstevel@tonic-gate }
2597c478bd9Sstevel@tonic-gate execl("/usr/sbin/wall", "wall", "-g", OPGRENT, (char *)NULL);
2607c478bd9Sstevel@tonic-gate saverr = errno;
2617c478bd9Sstevel@tonic-gate msg(gettext("execl: %s\n"), strerror(saverr));
2627c478bd9Sstevel@tonic-gate exit(1);
2637c478bd9Sstevel@tonic-gate default:
2647c478bd9Sstevel@tonic-gate break; /* parent */
2657c478bd9Sstevel@tonic-gate }
2667c478bd9Sstevel@tonic-gate
2677c478bd9Sstevel@tonic-gate close(fildes[1]);
2687c478bd9Sstevel@tonic-gate wall = fdopen(fildes[0], "r+");
2697c478bd9Sstevel@tonic-gate if (wall == (FILE *)NULL) {
2707c478bd9Sstevel@tonic-gate saverr = errno;
2717c478bd9Sstevel@tonic-gate msg(gettext("fdopen: %s\n"), strerror(saverr));
2727c478bd9Sstevel@tonic-gate return;
2737c478bd9Sstevel@tonic-gate }
2747c478bd9Sstevel@tonic-gate
2757c478bd9Sstevel@tonic-gate clock = time((time_t *)0);
2767c478bd9Sstevel@tonic-gate localclock = localtime(&clock);
2777c478bd9Sstevel@tonic-gate
2787c478bd9Sstevel@tonic-gate (void) fprintf(wall, gettext(
2797c478bd9Sstevel@tonic-gate "\n\007\007\007Message from the dump program to all operators at \
2807c478bd9Sstevel@tonic-gate %d:%02d ...\n\n%s"),
2817c478bd9Sstevel@tonic-gate localclock->tm_hour, localclock->tm_min, message);
2827c478bd9Sstevel@tonic-gate fclose(wall);
2837c478bd9Sstevel@tonic-gate
2847c478bd9Sstevel@tonic-gate while (wait((int *)0) != pid) {
2857c478bd9Sstevel@tonic-gate continue;
2867c478bd9Sstevel@tonic-gate /*LINTED [empty loop body]*/
2877c478bd9Sstevel@tonic-gate }
2887c478bd9Sstevel@tonic-gate }
2897c478bd9Sstevel@tonic-gate
2907c478bd9Sstevel@tonic-gate /*
2917c478bd9Sstevel@tonic-gate * print out an estimate of the amount of time left to do the dump
2927c478bd9Sstevel@tonic-gate */
2937c478bd9Sstevel@tonic-gate #define EST_SEC 600 /* every 10 minutes */
2947c478bd9Sstevel@tonic-gate void
timeest(int force,int blkswritten)295e0dfa398SToomas Soome timeest(int force, int blkswritten)
2967c478bd9Sstevel@tonic-gate {
2977c478bd9Sstevel@tonic-gate time_t tnow, deltat;
2987c478bd9Sstevel@tonic-gate char *msgp;
2997c478bd9Sstevel@tonic-gate
3007c478bd9Sstevel@tonic-gate if (tschedule == NULL)
3017c478bd9Sstevel@tonic-gate return;
3027c478bd9Sstevel@tonic-gate if (*tschedule == 0)
3037c478bd9Sstevel@tonic-gate *tschedule = time((time_t *)0) + EST_SEC;
3047c478bd9Sstevel@tonic-gate (void) time(&tnow);
3057c478bd9Sstevel@tonic-gate if ((force || tnow >= *tschedule) && blkswritten) {
3067c478bd9Sstevel@tonic-gate *tschedule = tnow + EST_SEC;
3077c478bd9Sstevel@tonic-gate if (!force && blkswritten < 50 * ntrec)
3087c478bd9Sstevel@tonic-gate return;
3097c478bd9Sstevel@tonic-gate deltat = (*telapsed + (tnow - *tstart_writing))
3107c478bd9Sstevel@tonic-gate * ((double)esize / blkswritten - 1.0);
3117c478bd9Sstevel@tonic-gate msgp = gettext("%3.2f%% done, finished in %d:%02d\n");
3127c478bd9Sstevel@tonic-gate msg(msgp, (blkswritten*100.0)/esize,
3137c478bd9Sstevel@tonic-gate deltat/3600, (deltat%3600)/60);
3147c478bd9Sstevel@tonic-gate }
3157c478bd9Sstevel@tonic-gate }
3167c478bd9Sstevel@tonic-gate
3177c478bd9Sstevel@tonic-gate #include <stdarg.h>
3187c478bd9Sstevel@tonic-gate
3197c478bd9Sstevel@tonic-gate /* VARARGS1 */
3207c478bd9Sstevel@tonic-gate void
msg(const char * fmt,...)3217c478bd9Sstevel@tonic-gate msg(const char *fmt, ...)
3227c478bd9Sstevel@tonic-gate {
3237c478bd9Sstevel@tonic-gate char buf[1024], *cp;
3247c478bd9Sstevel@tonic-gate size_t size;
3257c478bd9Sstevel@tonic-gate va_list args;
3267c478bd9Sstevel@tonic-gate
3277c478bd9Sstevel@tonic-gate va_start(args, fmt);
3287c478bd9Sstevel@tonic-gate (void) strcpy(buf, " DUMP: ");
3297c478bd9Sstevel@tonic-gate cp = &buf[strlen(buf)];
3307c478bd9Sstevel@tonic-gate #ifdef TDEBUG
3317c478bd9Sstevel@tonic-gate (void) sprintf(cp, "pid=%d ", getpid());
3327c478bd9Sstevel@tonic-gate cp = &buf[strlen(buf)];
3337c478bd9Sstevel@tonic-gate #endif
3347c478bd9Sstevel@tonic-gate /* don't need -1, vsnprintf does it right */
3357c478bd9Sstevel@tonic-gate /* LINTED pointer arithmetic result fits in size_t */
3367c478bd9Sstevel@tonic-gate size = ((size_t)sizeof (buf)) - (size_t)(cp - buf);
3377c478bd9Sstevel@tonic-gate (void) vsnprintf(cp, size, fmt, args);
3387c478bd9Sstevel@tonic-gate (void) fputs(buf, stderr);
3397c478bd9Sstevel@tonic-gate (void) fflush(stdout);
3407c478bd9Sstevel@tonic-gate (void) fflush(stderr);
3417c478bd9Sstevel@tonic-gate va_end(args);
3427c478bd9Sstevel@tonic-gate }
3437c478bd9Sstevel@tonic-gate
3447c478bd9Sstevel@tonic-gate /* VARARGS1 */
3457c478bd9Sstevel@tonic-gate void
msgtail(const char * fmt,...)3467c478bd9Sstevel@tonic-gate msgtail(const char *fmt, ...)
3477c478bd9Sstevel@tonic-gate {
3487c478bd9Sstevel@tonic-gate va_list args;
3497c478bd9Sstevel@tonic-gate
3507c478bd9Sstevel@tonic-gate va_start(args, fmt);
3517c478bd9Sstevel@tonic-gate (void) vfprintf(stderr, fmt, args);
3527c478bd9Sstevel@tonic-gate va_end(args);
3537c478bd9Sstevel@tonic-gate }
3547c478bd9Sstevel@tonic-gate
3557c478bd9Sstevel@tonic-gate #define MINUTES(x) ((x) * 60)
3567c478bd9Sstevel@tonic-gate
3577c478bd9Sstevel@tonic-gate /*
3587c478bd9Sstevel@tonic-gate * Tell the operator what has to be done;
3597c478bd9Sstevel@tonic-gate * we don't actually do it
3607c478bd9Sstevel@tonic-gate */
3617c478bd9Sstevel@tonic-gate void
lastdump(int arg)362e0dfa398SToomas Soome lastdump(int arg) /* w ==> just what to do; W ==> most recent dumps */
3637c478bd9Sstevel@tonic-gate {
3647c478bd9Sstevel@tonic-gate char *lastname;
3657c478bd9Sstevel@tonic-gate char *date;
3667c478bd9Sstevel@tonic-gate int i;
3677c478bd9Sstevel@tonic-gate time_t tnow, ddate;
3687c478bd9Sstevel@tonic-gate struct mntent *dt;
3697c478bd9Sstevel@tonic-gate int dumpme = 0;
3707c478bd9Sstevel@tonic-gate struct idates *itwalk;
3717c478bd9Sstevel@tonic-gate
3727c478bd9Sstevel@tonic-gate (void) time(&tnow);
3737c478bd9Sstevel@tonic-gate mnttabread(); /* /etc/fstab input */
3747c478bd9Sstevel@tonic-gate inititimes(); /* /etc/dumpdates input */
3757c478bd9Sstevel@tonic-gate
3767c478bd9Sstevel@tonic-gate /* Don't use msg(), this isn't a tell-the-world kind of thing */
3777c478bd9Sstevel@tonic-gate if (arg == 'w')
3787c478bd9Sstevel@tonic-gate (void) fprintf(stdout, gettext("Dump these file systems:\n"));
3797c478bd9Sstevel@tonic-gate else
3807c478bd9Sstevel@tonic-gate (void) fprintf(stdout, gettext(
3817c478bd9Sstevel@tonic-gate "Last dump(s) done (Dump '>' file systems):\n"));
3827c478bd9Sstevel@tonic-gate
3837c478bd9Sstevel@tonic-gate if (idatev != NULL) {
3847c478bd9Sstevel@tonic-gate qsort((char *)idatev, nidates, sizeof (*idatev), idatesort);
3857c478bd9Sstevel@tonic-gate lastname = "??";
3867c478bd9Sstevel@tonic-gate ITITERATE(i, itwalk) {
3877c478bd9Sstevel@tonic-gate if (strncmp(lastname, itwalk->id_name,
3887c478bd9Sstevel@tonic-gate sizeof (itwalk->id_name)) == 0)
3897c478bd9Sstevel@tonic-gate continue;
390bbf21555SRichard Lowe /* must be ctime(), per ufsdump(5) */
3917c478bd9Sstevel@tonic-gate ddate = itwalk->id_ddate;
3927c478bd9Sstevel@tonic-gate date = (char *)ctime(&ddate);
3937c478bd9Sstevel@tonic-gate date[16] = '\0'; /* blow away seconds and year */
3947c478bd9Sstevel@tonic-gate lastname = itwalk->id_name;
3957c478bd9Sstevel@tonic-gate dt = mnttabsearch(itwalk->id_name, 0);
3967c478bd9Sstevel@tonic-gate if ((time_t)(itwalk->id_ddate) < (tnow - DAY)) {
3977c478bd9Sstevel@tonic-gate dumpme = 1;
3987c478bd9Sstevel@tonic-gate }
3997c478bd9Sstevel@tonic-gate
4007c478bd9Sstevel@tonic-gate if ((arg == 'w') && dumpme) {
4017c478bd9Sstevel@tonic-gate /*
4027c478bd9Sstevel@tonic-gate * Handle the w option: print out file systems
4037c478bd9Sstevel@tonic-gate * which haven't been backed up within a day.
4047c478bd9Sstevel@tonic-gate */
4057c478bd9Sstevel@tonic-gate (void) printf(gettext("%8s\t(%6s)\n"),
4067c478bd9Sstevel@tonic-gate itwalk->id_name, dt ? dt->mnt_dir : "");
4077c478bd9Sstevel@tonic-gate }
4087c478bd9Sstevel@tonic-gate if (arg == 'W') {
4097c478bd9Sstevel@tonic-gate /*
4107c478bd9Sstevel@tonic-gate * Handle the W option: print out ALL
4117c478bd9Sstevel@tonic-gate * filesystems including recent dump dates and
4127c478bd9Sstevel@tonic-gate * dump levels. Mark the backup-needing
4137c478bd9Sstevel@tonic-gate * filesystems with a >.
4147c478bd9Sstevel@tonic-gate */
4157c478bd9Sstevel@tonic-gate (void) printf(gettext(
4167c478bd9Sstevel@tonic-gate "%c %8s\t(%6s) Last dump: Level %c, Date %s\n"),
4177c478bd9Sstevel@tonic-gate dumpme ? '>' : ' ',
4187c478bd9Sstevel@tonic-gate itwalk->id_name,
4197c478bd9Sstevel@tonic-gate dt ? dt->mnt_dir : "",
4207c478bd9Sstevel@tonic-gate (uchar_t)itwalk->id_incno,
4217c478bd9Sstevel@tonic-gate date);
4227c478bd9Sstevel@tonic-gate }
4237c478bd9Sstevel@tonic-gate dumpme = 0;
4247c478bd9Sstevel@tonic-gate }
4257c478bd9Sstevel@tonic-gate }
4267c478bd9Sstevel@tonic-gate }
4277c478bd9Sstevel@tonic-gate
4287c478bd9Sstevel@tonic-gate static int
idatesort(const void * v1,const void * v2)429e0dfa398SToomas Soome idatesort(const void *v1, const void *v2)
4307c478bd9Sstevel@tonic-gate {
4317c478bd9Sstevel@tonic-gate struct idates **p1 = (struct idates **)v1;
4327c478bd9Sstevel@tonic-gate struct idates **p2 = (struct idates **)v2;
4337c478bd9Sstevel@tonic-gate int diff;
4347c478bd9Sstevel@tonic-gate
4357c478bd9Sstevel@tonic-gate diff = strcoll((*p1)->id_name, (*p2)->id_name);
4367c478bd9Sstevel@tonic-gate if (diff == 0) {
4377c478bd9Sstevel@tonic-gate /*
4387c478bd9Sstevel@tonic-gate * Time may eventually become unsigned, so can't
4397c478bd9Sstevel@tonic-gate * rely on subtraction to give a useful result.
4407c478bd9Sstevel@tonic-gate * Note that we are sorting dates into reverse
4417c478bd9Sstevel@tonic-gate * order, so that we will report based on the
4427c478bd9Sstevel@tonic-gate * most-recent record for a particular filesystem.
4437c478bd9Sstevel@tonic-gate */
4447c478bd9Sstevel@tonic-gate if ((*p1)->id_ddate > (*p2)->id_ddate)
4457c478bd9Sstevel@tonic-gate diff = -1;
4467c478bd9Sstevel@tonic-gate else if ((*p1)->id_ddate < (*p2)->id_ddate)
4477c478bd9Sstevel@tonic-gate diff = 1;
4487c478bd9Sstevel@tonic-gate }
4497c478bd9Sstevel@tonic-gate return (diff);
4507c478bd9Sstevel@tonic-gate }
451