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
query(question)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
addem(s)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
query_once(question,def)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__
alarmcatch(void)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
interrupt(sig)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
broadcast(message)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
timeest(force,blkswritten)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
msg(const char * fmt,...)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
msgtail(const char * fmt,...)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
lastdump(arg)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
idatesort(v1,v2)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