xref: /freebsd/sbin/dump/optr.c (revision bfa0b2984deca9e2d33082606535cca9b008c2ad)
18fae3551SRodney W. Grimes /*-
28fae3551SRodney W. Grimes  * Copyright (c) 1980, 1988, 1993
38fae3551SRodney W. Grimes  *	The Regents of the University of California.  All rights reserved.
48fae3551SRodney W. Grimes  *
58fae3551SRodney W. Grimes  * Redistribution and use in source and binary forms, with or without
68fae3551SRodney W. Grimes  * modification, are permitted provided that the following conditions
78fae3551SRodney W. Grimes  * are met:
88fae3551SRodney W. Grimes  * 1. Redistributions of source code must retain the above copyright
98fae3551SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer.
108fae3551SRodney W. Grimes  * 2. Redistributions in binary form must reproduce the above copyright
118fae3551SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer in the
128fae3551SRodney W. Grimes  *    documentation and/or other materials provided with the distribution.
138fae3551SRodney W. Grimes  * 3. All advertising materials mentioning features or use of this software
148fae3551SRodney W. Grimes  *    must display the following acknowledgement:
158fae3551SRodney W. Grimes  *	This product includes software developed by the University of
168fae3551SRodney W. Grimes  *	California, Berkeley and its contributors.
178fae3551SRodney W. Grimes  * 4. Neither the name of the University nor the names of its contributors
188fae3551SRodney W. Grimes  *    may be used to endorse or promote products derived from this software
198fae3551SRodney W. Grimes  *    without specific prior written permission.
208fae3551SRodney W. Grimes  *
218fae3551SRodney W. Grimes  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
228fae3551SRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
238fae3551SRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
248fae3551SRodney W. Grimes  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
258fae3551SRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
268fae3551SRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
278fae3551SRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
288fae3551SRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
298fae3551SRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
308fae3551SRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
318fae3551SRodney W. Grimes  * SUCH DAMAGE.
328fae3551SRodney W. Grimes  */
338fae3551SRodney W. Grimes 
348fae3551SRodney W. Grimes #ifndef lint
357580ffbbSPhilippe Charnier #if 0
368fae3551SRodney W. Grimes static char sccsid[] = "@(#)optr.c	8.2 (Berkeley) 1/6/94";
377580ffbbSPhilippe Charnier #endif
387580ffbbSPhilippe Charnier static const char rcsid[] =
397f3dea24SPeter Wemm   "$FreeBSD$";
408fae3551SRodney W. Grimes #endif /* not lint */
418fae3551SRodney W. Grimes 
428fae3551SRodney W. Grimes #include <sys/param.h>
438fae3551SRodney W. Grimes #include <sys/wait.h>
448fae3551SRodney W. Grimes #include <sys/time.h>
458fae3551SRodney W. Grimes 
468fae3551SRodney W. Grimes #include <errno.h>
478fae3551SRodney W. Grimes #include <fstab.h>
488fae3551SRodney W. Grimes #include <grp.h>
498fae3551SRodney W. Grimes #include <stdio.h>
508fae3551SRodney W. Grimes #include <stdlib.h>
518fae3551SRodney W. Grimes #include <string.h>
528fae3551SRodney W. Grimes #include <stdarg.h>
538fae3551SRodney W. Grimes #include <unistd.h>
548fae3551SRodney W. Grimes #include <utmp.h>
558fae3551SRodney W. Grimes 
568fae3551SRodney W. Grimes #include "dump.h"
578fae3551SRodney W. Grimes #include "pathnames.h"
588fae3551SRodney W. Grimes 
598fae3551SRodney W. Grimes void	alarmcatch __P((/* int, int */));
608fae3551SRodney W. Grimes int	datesort __P((const void *, const void *));
618fae3551SRodney W. Grimes static	void sendmes __P((char *, char *));
628fae3551SRodney W. Grimes 
638fae3551SRodney W. Grimes /*
648fae3551SRodney W. Grimes  *	Query the operator; This previously-fascist piece of code
658fae3551SRodney W. Grimes  *	no longer requires an exact response.
668fae3551SRodney W. Grimes  *	It is intended to protect dump aborting by inquisitive
678fae3551SRodney W. Grimes  *	people banging on the console terminal to see what is
688fae3551SRodney W. Grimes  *	happening which might cause dump to croak, destroying
698fae3551SRodney W. Grimes  *	a large number of hours of work.
708fae3551SRodney W. Grimes  *
718fae3551SRodney W. Grimes  *	Every 2 minutes we reprint the message, alerting others
728fae3551SRodney W. Grimes  *	that dump needs attention.
738fae3551SRodney W. Grimes  */
748fae3551SRodney W. Grimes static	int timeout;
758fae3551SRodney W. Grimes static	char *attnmessage;		/* attention message */
768fae3551SRodney W. Grimes 
778fae3551SRodney W. Grimes int
788fae3551SRodney W. Grimes query(question)
798fae3551SRodney W. Grimes 	char	*question;
808fae3551SRodney W. Grimes {
818fae3551SRodney W. Grimes 	char	replybuffer[64];
828fae3551SRodney W. Grimes 	int	back, errcount;
838fae3551SRodney W. Grimes 	FILE	*mytty;
848fae3551SRodney W. Grimes 
858fae3551SRodney W. Grimes 	if ((mytty = fopen(_PATH_TTY, "r")) == NULL)
868fae3551SRodney W. Grimes 		quit("fopen on %s fails: %s\n", _PATH_TTY, strerror(errno));
878fae3551SRodney W. Grimes 	attnmessage = question;
888fae3551SRodney W. Grimes 	timeout = 0;
898fae3551SRodney W. Grimes 	alarmcatch();
908fae3551SRodney W. Grimes 	back = -1;
918fae3551SRodney W. Grimes 	errcount = 0;
928fae3551SRodney W. Grimes 	do {
938fae3551SRodney W. Grimes 		if (fgets(replybuffer, 63, mytty) == NULL) {
948fae3551SRodney W. Grimes 			clearerr(mytty);
958fae3551SRodney W. Grimes 			if (++errcount > 30)	/* XXX	ugly */
968fae3551SRodney W. Grimes 				quit("excessive operator query failures\n");
978fae3551SRodney W. Grimes 		} else if (replybuffer[0] == 'y' || replybuffer[0] == 'Y') {
988fae3551SRodney W. Grimes 			back = 1;
998fae3551SRodney W. Grimes 		} else if (replybuffer[0] == 'n' || replybuffer[0] == 'N') {
1008fae3551SRodney W. Grimes 			back = 0;
1018fae3551SRodney W. Grimes 		} else {
1028fae3551SRodney W. Grimes 			(void) fprintf(stderr,
1038fae3551SRodney W. Grimes 			    "  DUMP: \"Yes\" or \"No\"?\n");
1048fae3551SRodney W. Grimes 			(void) fprintf(stderr,
1058fae3551SRodney W. Grimes 			    "  DUMP: %s: (\"yes\" or \"no\") ", question);
1068fae3551SRodney W. Grimes 		}
1078fae3551SRodney W. Grimes 	} while (back < 0);
1088fae3551SRodney W. Grimes 
1098fae3551SRodney W. Grimes 	/*
1108fae3551SRodney W. Grimes 	 *	Turn off the alarm, and reset the signal to trap out..
1118fae3551SRodney W. Grimes 	 */
1128fae3551SRodney W. Grimes 	(void) alarm(0);
1138fae3551SRodney W. Grimes 	if (signal(SIGALRM, sig) == SIG_IGN)
1148fae3551SRodney W. Grimes 		signal(SIGALRM, SIG_IGN);
1158fae3551SRodney W. Grimes 	(void) fclose(mytty);
1168fae3551SRodney W. Grimes 	return(back);
1178fae3551SRodney W. Grimes }
1188fae3551SRodney W. Grimes 
1198fae3551SRodney W. Grimes char lastmsg[100];
1208fae3551SRodney W. Grimes 
1218fae3551SRodney W. Grimes /*
1228fae3551SRodney W. Grimes  *	Alert the console operator, and enable the alarm clock to
1238fae3551SRodney W. Grimes  *	sleep for 2 minutes in case nobody comes to satisfy dump
1248fae3551SRodney W. Grimes  */
1258fae3551SRodney W. Grimes void
1268fae3551SRodney W. Grimes alarmcatch()
1278fae3551SRodney W. Grimes {
1288fae3551SRodney W. Grimes 	if (notify == 0) {
1298fae3551SRodney W. Grimes 		if (timeout == 0)
1308fae3551SRodney W. Grimes 			(void) fprintf(stderr,
1318fae3551SRodney W. Grimes 			    "  DUMP: %s: (\"yes\" or \"no\") ",
1328fae3551SRodney W. Grimes 			    attnmessage);
1338fae3551SRodney W. Grimes 		else
134bfa0b298SPoul-Henning Kamp 			msgtail("\a\a");
1358fae3551SRodney W. Grimes 	} else {
1368fae3551SRodney W. Grimes 		if (timeout) {
1378fae3551SRodney W. Grimes 			msgtail("\n");
1388fae3551SRodney W. Grimes 			broadcast("");		/* just print last msg */
1398fae3551SRodney W. Grimes 		}
1408fae3551SRodney W. Grimes 		(void) fprintf(stderr,"  DUMP: %s: (\"yes\" or \"no\") ",
1418fae3551SRodney W. Grimes 		    attnmessage);
1428fae3551SRodney W. Grimes 	}
1438fae3551SRodney W. Grimes 	signal(SIGALRM, alarmcatch);
1448fae3551SRodney W. Grimes 	(void) alarm(120);
1458fae3551SRodney W. Grimes 	timeout = 1;
1468fae3551SRodney W. Grimes }
1478fae3551SRodney W. Grimes 
1488fae3551SRodney W. Grimes /*
1498fae3551SRodney W. Grimes  *	Here if an inquisitive operator interrupts the dump program
1508fae3551SRodney W. Grimes  */
1518fae3551SRodney W. Grimes void
1528fae3551SRodney W. Grimes interrupt(signo)
1538fae3551SRodney W. Grimes 	int signo;
1548fae3551SRodney W. Grimes {
1558fae3551SRodney W. Grimes 	msg("Interrupt received.\n");
1568fae3551SRodney W. Grimes 	if (query("Do you want to abort dump?"))
1578fae3551SRodney W. Grimes 		dumpabort(0);
1588fae3551SRodney W. Grimes }
1598fae3551SRodney W. Grimes 
1608fae3551SRodney W. Grimes /*
1618fae3551SRodney W. Grimes  *	The following variables and routines manage alerting
1628fae3551SRodney W. Grimes  *	operators to the status of dump.
1638fae3551SRodney W. Grimes  *	This works much like wall(1) does.
1648fae3551SRodney W. Grimes  */
1658fae3551SRodney W. Grimes struct	group *gp;
1668fae3551SRodney W. Grimes 
1678fae3551SRodney W. Grimes /*
1688fae3551SRodney W. Grimes  *	Get the names from the group entry "operator" to notify.
1698fae3551SRodney W. Grimes  */
1708fae3551SRodney W. Grimes void
1718fae3551SRodney W. Grimes set_operators()
1728fae3551SRodney W. Grimes {
1738fae3551SRodney W. Grimes 	if (!notify)		/*not going to notify*/
1748fae3551SRodney W. Grimes 		return;
1758fae3551SRodney W. Grimes 	gp = getgrnam(OPGRENT);
1768fae3551SRodney W. Grimes 	(void) endgrent();
1778fae3551SRodney W. Grimes 	if (gp == NULL) {
1788fae3551SRodney W. Grimes 		msg("No group entry for %s.\n", OPGRENT);
1798fae3551SRodney W. Grimes 		notify = 0;
1808fae3551SRodney W. Grimes 		return;
1818fae3551SRodney W. Grimes 	}
1828fae3551SRodney W. Grimes }
1838fae3551SRodney W. Grimes 
1848fae3551SRodney W. Grimes struct tm *localclock;
1858fae3551SRodney W. Grimes 
1868fae3551SRodney W. Grimes /*
1878fae3551SRodney W. Grimes  *	We fork a child to do the actual broadcasting, so
1888fae3551SRodney W. Grimes  *	that the process control groups are not messed up
1898fae3551SRodney W. Grimes  */
1908fae3551SRodney W. Grimes void
1918fae3551SRodney W. Grimes broadcast(message)
1928fae3551SRodney W. Grimes 	char	*message;
1938fae3551SRodney W. Grimes {
1948fae3551SRodney W. Grimes 	time_t		clock;
1958fae3551SRodney W. Grimes 	FILE	*f_utmp;
1968fae3551SRodney W. Grimes 	struct	utmp	utmp;
1978fae3551SRodney W. Grimes 	char	**np;
1988fae3551SRodney W. Grimes 	int	pid, s;
1998fae3551SRodney W. Grimes 
2008fae3551SRodney W. Grimes 	if (!notify || gp == NULL)
2018fae3551SRodney W. Grimes 		return;
2028fae3551SRodney W. Grimes 
2038fae3551SRodney W. Grimes 	switch (pid = fork()) {
2048fae3551SRodney W. Grimes 	case -1:
2058fae3551SRodney W. Grimes 		return;
2068fae3551SRodney W. Grimes 	case 0:
2078fae3551SRodney W. Grimes 		break;
2088fae3551SRodney W. Grimes 	default:
2098fae3551SRodney W. Grimes 		while (wait(&s) != pid)
2108fae3551SRodney W. Grimes 			continue;
2118fae3551SRodney W. Grimes 		return;
2128fae3551SRodney W. Grimes 	}
2138fae3551SRodney W. Grimes 
2148fae3551SRodney W. Grimes 	clock = time((time_t *)0);
2158fae3551SRodney W. Grimes 	localclock = localtime(&clock);
2168fae3551SRodney W. Grimes 
2178fae3551SRodney W. Grimes 	if ((f_utmp = fopen(_PATH_UTMP, "r")) == NULL) {
2188fae3551SRodney W. Grimes 		msg("Cannot open %s: %s\n", _PATH_UTMP, strerror(errno));
2198fae3551SRodney W. Grimes 		return;
2208fae3551SRodney W. Grimes 	}
2218fae3551SRodney W. Grimes 
2228fae3551SRodney W. Grimes 	while (!feof(f_utmp)) {
2238fae3551SRodney W. Grimes 		if (fread((char *) &utmp, sizeof (struct utmp), 1, f_utmp) != 1)
2248fae3551SRodney W. Grimes 			break;
2258fae3551SRodney W. Grimes 		if (utmp.ut_name[0] == 0)
2268fae3551SRodney W. Grimes 			continue;
2278fae3551SRodney W. Grimes 		for (np = gp->gr_mem; *np; np++) {
2288fae3551SRodney W. Grimes 			if (strncmp(*np, utmp.ut_name, sizeof(utmp.ut_name)) != 0)
2298fae3551SRodney W. Grimes 				continue;
2308fae3551SRodney W. Grimes 			/*
2318fae3551SRodney W. Grimes 			 *	Do not send messages to operators on dialups
2328fae3551SRodney W. Grimes 			 */
2338fae3551SRodney W. Grimes 			if (strncmp(utmp.ut_line, DIALUP, strlen(DIALUP)) == 0)
2348fae3551SRodney W. Grimes 				continue;
2358fae3551SRodney W. Grimes #ifdef DEBUG
2368fae3551SRodney W. Grimes 			msg("Message to %s at %s\n", *np, utmp.ut_line);
2378fae3551SRodney W. Grimes #endif
2388fae3551SRodney W. Grimes 			sendmes(utmp.ut_line, message);
2398fae3551SRodney W. Grimes 		}
2408fae3551SRodney W. Grimes 	}
2418fae3551SRodney W. Grimes 	(void) fclose(f_utmp);
2428fae3551SRodney W. Grimes 	Exit(0);	/* the wait in this same routine will catch this */
2438fae3551SRodney W. Grimes 	/* NOTREACHED */
2448fae3551SRodney W. Grimes }
2458fae3551SRodney W. Grimes 
2468fae3551SRodney W. Grimes static void
2478fae3551SRodney W. Grimes sendmes(tty, message)
2488fae3551SRodney W. Grimes 	char *tty, *message;
2498fae3551SRodney W. Grimes {
250f5dcc2f1SWarner Losh 	char t[MAXPATHLEN], buf[BUFSIZ];
2518fae3551SRodney W. Grimes 	register char *cp;
2528fae3551SRodney W. Grimes 	int lmsg = 1;
2538fae3551SRodney W. Grimes 	FILE *f_tty;
2548fae3551SRodney W. Grimes 
2558fae3551SRodney W. Grimes 	(void) strcpy(t, _PATH_DEV);
256f5dcc2f1SWarner Losh 	(void) strncat(t, tty, sizeof t - strlen(_PATH_DEV) - 1);
2578fae3551SRodney W. Grimes 
2588fae3551SRodney W. Grimes 	if ((f_tty = fopen(t, "w")) != NULL) {
2598fae3551SRodney W. Grimes 		setbuf(f_tty, buf);
2608fae3551SRodney W. Grimes 		(void) fprintf(f_tty,
2618fae3551SRodney W. Grimes 		    "\n\
262bfa0b298SPoul-Henning Kamp \a\a\aMessage from the dump program to all operators at %d:%02d ...\r\n\n\
2638fae3551SRodney W. Grimes DUMP: NEEDS ATTENTION: ",
2648fae3551SRodney W. Grimes 		    localclock->tm_hour, localclock->tm_min);
2658fae3551SRodney W. Grimes 		for (cp = lastmsg; ; cp++) {
2668fae3551SRodney W. Grimes 			if (*cp == '\0') {
2678fae3551SRodney W. Grimes 				if (lmsg) {
2688fae3551SRodney W. Grimes 					cp = message;
2698fae3551SRodney W. Grimes 					if (*cp == '\0')
2708fae3551SRodney W. Grimes 						break;
2718fae3551SRodney W. Grimes 					lmsg = 0;
2728fae3551SRodney W. Grimes 				} else
2738fae3551SRodney W. Grimes 					break;
2748fae3551SRodney W. Grimes 			}
2758fae3551SRodney W. Grimes 			if (*cp == '\n')
2768fae3551SRodney W. Grimes 				(void) putc('\r', f_tty);
2778fae3551SRodney W. Grimes 			(void) putc(*cp, f_tty);
2788fae3551SRodney W. Grimes 		}
2798fae3551SRodney W. Grimes 		(void) fclose(f_tty);
2808fae3551SRodney W. Grimes 	}
2818fae3551SRodney W. Grimes }
2828fae3551SRodney W. Grimes 
2838fae3551SRodney W. Grimes /*
2848fae3551SRodney W. Grimes  *	print out an estimate of the amount of time left to do the dump
2858fae3551SRodney W. Grimes  */
2868fae3551SRodney W. Grimes 
2878fae3551SRodney W. Grimes time_t	tschedule = 0;
2888fae3551SRodney W. Grimes 
2898fae3551SRodney W. Grimes void
2908fae3551SRodney W. Grimes timeest()
2918fae3551SRodney W. Grimes {
2928fae3551SRodney W. Grimes 	time_t	tnow, deltat;
2938fae3551SRodney W. Grimes 
2948fae3551SRodney W. Grimes 	(void) time((time_t *) &tnow);
2958fae3551SRodney W. Grimes 	if (tnow >= tschedule) {
2968fae3551SRodney W. Grimes 		tschedule = tnow + 300;
2978fae3551SRodney W. Grimes 		if (blockswritten < 500)
2988fae3551SRodney W. Grimes 			return;
2998fae3551SRodney W. Grimes 		deltat = tstart_writing - tnow +
3008fae3551SRodney W. Grimes 			(1.0 * (tnow - tstart_writing))
3018fae3551SRodney W. Grimes 			/ blockswritten * tapesize;
3028fae3551SRodney W. Grimes 		msg("%3.2f%% done, finished in %d:%02d\n",
3038fae3551SRodney W. Grimes 			(blockswritten * 100.0) / tapesize,
3048fae3551SRodney W. Grimes 			deltat / 3600, (deltat % 3600) / 60);
3058fae3551SRodney W. Grimes 	}
3068fae3551SRodney W. Grimes }
3078fae3551SRodney W. Grimes 
3088fae3551SRodney W. Grimes void
3098fae3551SRodney W. Grimes #if __STDC__
3108fae3551SRodney W. Grimes msg(const char *fmt, ...)
3118fae3551SRodney W. Grimes #else
3128fae3551SRodney W. Grimes msg(fmt, va_alist)
3138fae3551SRodney W. Grimes 	char *fmt;
3148fae3551SRodney W. Grimes 	va_dcl
3158fae3551SRodney W. Grimes #endif
3168fae3551SRodney W. Grimes {
3178fae3551SRodney W. Grimes 	va_list ap;
3188fae3551SRodney W. Grimes 
3198fae3551SRodney W. Grimes 	(void) fprintf(stderr,"  DUMP: ");
3208fae3551SRodney W. Grimes #ifdef TDEBUG
3218fae3551SRodney W. Grimes 	(void) fprintf(stderr, "pid=%d ", getpid());
3228fae3551SRodney W. Grimes #endif
3238fae3551SRodney W. Grimes #if __STDC__
3248fae3551SRodney W. Grimes 	va_start(ap, fmt);
3258fae3551SRodney W. Grimes #else
3268fae3551SRodney W. Grimes 	va_start(ap);
3278fae3551SRodney W. Grimes #endif
3288fae3551SRodney W. Grimes 	(void) vfprintf(stderr, fmt, ap);
3298fae3551SRodney W. Grimes 	(void) fflush(stdout);
3308fae3551SRodney W. Grimes 	(void) fflush(stderr);
331a7d7b470SWarner Losh 	(void) vsnprintf(lastmsg, sizeof(lastmsg), fmt, ap);
3328fae3551SRodney W. Grimes 	va_end(ap);
3338fae3551SRodney W. Grimes }
3348fae3551SRodney W. Grimes 
3358fae3551SRodney W. Grimes void
3368fae3551SRodney W. Grimes #if __STDC__
3378fae3551SRodney W. Grimes msgtail(const char *fmt, ...)
3388fae3551SRodney W. Grimes #else
3398fae3551SRodney W. Grimes msgtail(fmt, va_alist)
3408fae3551SRodney W. Grimes 	char *fmt;
3418fae3551SRodney W. Grimes 	va_dcl
3428fae3551SRodney W. Grimes #endif
3438fae3551SRodney W. Grimes {
3448fae3551SRodney W. Grimes 	va_list ap;
3458fae3551SRodney W. Grimes #if __STDC__
3468fae3551SRodney W. Grimes 	va_start(ap, fmt);
3478fae3551SRodney W. Grimes #else
3488fae3551SRodney W. Grimes 	va_start(ap);
3498fae3551SRodney W. Grimes #endif
3508fae3551SRodney W. Grimes 	(void) vfprintf(stderr, fmt, ap);
3518fae3551SRodney W. Grimes 	va_end(ap);
3528fae3551SRodney W. Grimes }
3538fae3551SRodney W. Grimes 
3548fae3551SRodney W. Grimes void
3558fae3551SRodney W. Grimes #if __STDC__
3568fae3551SRodney W. Grimes quit(const char *fmt, ...)
3578fae3551SRodney W. Grimes #else
3588fae3551SRodney W. Grimes quit(fmt, va_alist)
3598fae3551SRodney W. Grimes 	char *fmt;
3608fae3551SRodney W. Grimes 	va_dcl
3618fae3551SRodney W. Grimes #endif
3628fae3551SRodney W. Grimes {
3638fae3551SRodney W. Grimes 	va_list ap;
3648fae3551SRodney W. Grimes 
3658fae3551SRodney W. Grimes 	(void) fprintf(stderr,"  DUMP: ");
3668fae3551SRodney W. Grimes #ifdef TDEBUG
3678fae3551SRodney W. Grimes 	(void) fprintf(stderr, "pid=%d ", getpid());
3688fae3551SRodney W. Grimes #endif
3698fae3551SRodney W. Grimes #if __STDC__
3708fae3551SRodney W. Grimes 	va_start(ap, fmt);
3718fae3551SRodney W. Grimes #else
3728fae3551SRodney W. Grimes 	va_start(ap);
3738fae3551SRodney W. Grimes #endif
3748fae3551SRodney W. Grimes 	(void) vfprintf(stderr, fmt, ap);
3758fae3551SRodney W. Grimes 	va_end(ap);
3768fae3551SRodney W. Grimes 	(void) fflush(stdout);
3778fae3551SRodney W. Grimes 	(void) fflush(stderr);
3788fae3551SRodney W. Grimes 	dumpabort(0);
3798fae3551SRodney W. Grimes }
3808fae3551SRodney W. Grimes 
3818fae3551SRodney W. Grimes /*
3828fae3551SRodney W. Grimes  *	Tell the operator what has to be done;
3838fae3551SRodney W. Grimes  *	we don't actually do it
3848fae3551SRodney W. Grimes  */
3858fae3551SRodney W. Grimes 
3868fae3551SRodney W. Grimes struct fstab *
3878fae3551SRodney W. Grimes allocfsent(fs)
3888fae3551SRodney W. Grimes 	register struct fstab *fs;
3898fae3551SRodney W. Grimes {
3908fae3551SRodney W. Grimes 	register struct fstab *new;
3918fae3551SRodney W. Grimes 
3928fae3551SRodney W. Grimes 	new = (struct fstab *)malloc(sizeof (*fs));
3938fae3551SRodney W. Grimes 	if (new == NULL ||
3948fae3551SRodney W. Grimes 	    (new->fs_file = strdup(fs->fs_file)) == NULL ||
3958fae3551SRodney W. Grimes 	    (new->fs_type = strdup(fs->fs_type)) == NULL ||
3968fae3551SRodney W. Grimes 	    (new->fs_spec = strdup(fs->fs_spec)) == NULL)
3978fae3551SRodney W. Grimes 		quit("%s\n", strerror(errno));
3988fae3551SRodney W. Grimes 	new->fs_passno = fs->fs_passno;
3998fae3551SRodney W. Grimes 	new->fs_freq = fs->fs_freq;
4008fae3551SRodney W. Grimes 	return (new);
4018fae3551SRodney W. Grimes }
4028fae3551SRodney W. Grimes 
4038fae3551SRodney W. Grimes struct	pfstab {
4048fae3551SRodney W. Grimes 	struct	pfstab *pf_next;
4058fae3551SRodney W. Grimes 	struct	fstab *pf_fstab;
4068fae3551SRodney W. Grimes };
4078fae3551SRodney W. Grimes 
4088fae3551SRodney W. Grimes static	struct pfstab *table;
4098fae3551SRodney W. Grimes 
4108fae3551SRodney W. Grimes void
4118fae3551SRodney W. Grimes getfstab()
4128fae3551SRodney W. Grimes {
4138fae3551SRodney W. Grimes 	register struct fstab *fs;
4148fae3551SRodney W. Grimes 	register struct pfstab *pf;
4158fae3551SRodney W. Grimes 
4168fae3551SRodney W. Grimes 	if (setfsent() == 0) {
4178fae3551SRodney W. Grimes 		msg("Can't open %s for dump table information: %s\n",
4188fae3551SRodney W. Grimes 		    _PATH_FSTAB, strerror(errno));
4198fae3551SRodney W. Grimes 		return;
4208fae3551SRodney W. Grimes 	}
4218fae3551SRodney W. Grimes 	while ((fs = getfsent()) != NULL) {
4228fae3551SRodney W. Grimes 		if (strcmp(fs->fs_type, FSTAB_RW) &&
4238fae3551SRodney W. Grimes 		    strcmp(fs->fs_type, FSTAB_RO) &&
4248fae3551SRodney W. Grimes 		    strcmp(fs->fs_type, FSTAB_RQ))
4258fae3551SRodney W. Grimes 			continue;
4268fae3551SRodney W. Grimes 		fs = allocfsent(fs);
4278fae3551SRodney W. Grimes 		if ((pf = (struct pfstab *)malloc(sizeof (*pf))) == NULL)
4288fae3551SRodney W. Grimes 			quit("%s\n", strerror(errno));
4298fae3551SRodney W. Grimes 		pf->pf_fstab = fs;
4308fae3551SRodney W. Grimes 		pf->pf_next = table;
4318fae3551SRodney W. Grimes 		table = pf;
4328fae3551SRodney W. Grimes 	}
4338fae3551SRodney W. Grimes 	(void) endfsent();
4348fae3551SRodney W. Grimes }
4358fae3551SRodney W. Grimes 
4368fae3551SRodney W. Grimes /*
4378fae3551SRodney W. Grimes  * Search in the fstab for a file name.
4388fae3551SRodney W. Grimes  * This file name can be either the special or the path file name.
4398fae3551SRodney W. Grimes  *
4408fae3551SRodney W. Grimes  * The file name can omit the leading '/'.
4418fae3551SRodney W. Grimes  */
4428fae3551SRodney W. Grimes struct fstab *
4438fae3551SRodney W. Grimes fstabsearch(key)
4448fae3551SRodney W. Grimes 	char *key;
4458fae3551SRodney W. Grimes {
4468fae3551SRodney W. Grimes 	register struct pfstab *pf;
4478fae3551SRodney W. Grimes 	register struct fstab *fs;
4488fae3551SRodney W. Grimes 	char *rn;
4498fae3551SRodney W. Grimes 
4508fae3551SRodney W. Grimes 	for (pf = table; pf != NULL; pf = pf->pf_next) {
4518fae3551SRodney W. Grimes 		fs = pf->pf_fstab;
4528fae3551SRodney W. Grimes 		if (strcmp(fs->fs_file, key) == 0 ||
4538fae3551SRodney W. Grimes 		    strcmp(fs->fs_spec, key) == 0)
4548fae3551SRodney W. Grimes 			return (fs);
4558fae3551SRodney W. Grimes 		rn = rawname(fs->fs_spec);
4568fae3551SRodney W. Grimes 		if (rn != NULL && strcmp(rn, key) == 0)
4578fae3551SRodney W. Grimes 			return (fs);
4588fae3551SRodney W. Grimes 		if (key[0] != '/') {
4598fae3551SRodney W. Grimes 			if (*fs->fs_spec == '/' &&
4608fae3551SRodney W. Grimes 			    strcmp(fs->fs_spec + 1, key) == 0)
4618fae3551SRodney W. Grimes 				return (fs);
4628fae3551SRodney W. Grimes 			if (*fs->fs_file == '/' &&
4638fae3551SRodney W. Grimes 			    strcmp(fs->fs_file + 1, key) == 0)
4648fae3551SRodney W. Grimes 				return (fs);
4658fae3551SRodney W. Grimes 		}
4668fae3551SRodney W. Grimes 	}
4678fae3551SRodney W. Grimes 	return (NULL);
4688fae3551SRodney W. Grimes }
4698fae3551SRodney W. Grimes 
4708fae3551SRodney W. Grimes /*
4718fae3551SRodney W. Grimes  *	Tell the operator what to do
4728fae3551SRodney W. Grimes  */
4738fae3551SRodney W. Grimes void
4748fae3551SRodney W. Grimes lastdump(arg)
4758fae3551SRodney W. Grimes 	char	arg;	/* w ==> just what to do; W ==> most recent dumps */
4768fae3551SRodney W. Grimes {
4778fae3551SRodney W. Grimes 	register int i;
4788fae3551SRodney W. Grimes 	register struct fstab *dt;
4798fae3551SRodney W. Grimes 	register struct dumpdates *dtwalk;
4808fae3551SRodney W. Grimes 	char *lastname, *date;
4818fae3551SRodney W. Grimes 	int dumpme;
482a741b779SJordan K. Hubbard 	time_t tnow;
483a741b779SJordan K. Hubbard 	struct tm *tlast;
4848fae3551SRodney W. Grimes 
4858fae3551SRodney W. Grimes 	(void) time(&tnow);
4868fae3551SRodney W. Grimes 	getfstab();		/* /etc/fstab input */
4878fae3551SRodney W. Grimes 	initdumptimes();	/* /etc/dumpdates input */
4888fae3551SRodney W. Grimes 	qsort((char *) ddatev, nddates, sizeof(struct dumpdates *), datesort);
4898fae3551SRodney W. Grimes 
4908fae3551SRodney W. Grimes 	if (arg == 'w')
4918fae3551SRodney W. Grimes 		(void) printf("Dump these file systems:\n");
4928fae3551SRodney W. Grimes 	else
4938fae3551SRodney W. Grimes 		(void) printf("Last dump(s) done (Dump '>' file systems):\n");
4948fae3551SRodney W. Grimes 	lastname = "??";
4958fae3551SRodney W. Grimes 	ITITERATE(i, dtwalk) {
4968fae3551SRodney W. Grimes 		if (strncmp(lastname, dtwalk->dd_name,
4978fae3551SRodney W. Grimes 		    sizeof(dtwalk->dd_name)) == 0)
4988fae3551SRodney W. Grimes 			continue;
499a741b779SJordan K. Hubbard 		date = (char *)ctime(&dtwalk->dd_ddate);
5008fae3551SRodney W. Grimes 		date[16] = '\0';	/* blast away seconds and year */
5018fae3551SRodney W. Grimes 		lastname = dtwalk->dd_name;
5028fae3551SRodney W. Grimes 		dt = fstabsearch(dtwalk->dd_name);
503a741b779SJordan K. Hubbard 		dumpme = (dt != NULL && dt->fs_freq != 0);
504a741b779SJordan K. Hubbard 		if (dumpme) {
505a741b779SJordan K. Hubbard 		    tlast = localtime(&dtwalk->dd_ddate);
506a741b779SJordan K. Hubbard 		    dumpme = tnow > (dtwalk->dd_ddate - (tlast->tm_hour * 3600)
507a741b779SJordan K. Hubbard 				     - (tlast->tm_min * 60) - tlast->tm_sec
508a741b779SJordan K. Hubbard 				     + (dt->fs_freq * 86400));
509a741b779SJordan K. Hubbard 		};
5108fae3551SRodney W. Grimes 		if (arg != 'w' || dumpme)
5118fae3551SRodney W. Grimes 			(void) printf(
5128fae3551SRodney W. Grimes 			    "%c %8s\t(%6s) Last dump: Level %c, Date %s\n",
5138fae3551SRodney W. Grimes 			    dumpme && (arg != 'w') ? '>' : ' ',
5148fae3551SRodney W. Grimes 			    dtwalk->dd_name,
5158fae3551SRodney W. Grimes 			    dt ? dt->fs_file : "",
5168fae3551SRodney W. Grimes 			    dtwalk->dd_level,
5178fae3551SRodney W. Grimes 			    date);
5188fae3551SRodney W. Grimes 	}
5198fae3551SRodney W. Grimes }
5208fae3551SRodney W. Grimes 
5218fae3551SRodney W. Grimes int
5228fae3551SRodney W. Grimes datesort(a1, a2)
5238fae3551SRodney W. Grimes 	const void *a1, *a2;
5248fae3551SRodney W. Grimes {
5258fae3551SRodney W. Grimes 	struct dumpdates *d1 = *(struct dumpdates **)a1;
5268fae3551SRodney W. Grimes 	struct dumpdates *d2 = *(struct dumpdates **)a2;
5278fae3551SRodney W. Grimes 	int diff;
5288fae3551SRodney W. Grimes 
5298fae3551SRodney W. Grimes 	diff = strncmp(d1->dd_name, d2->dd_name, sizeof(d1->dd_name));
5308fae3551SRodney W. Grimes 	if (diff == 0)
5318fae3551SRodney W. Grimes 		return (d2->dd_ddate - d1->dd_ddate);
5328fae3551SRodney W. Grimes 	return (diff);
5338fae3551SRodney W. Grimes }
534