xref: /onnv-gate/usr/src/cmd/vi/port/exrecover.c (revision 13093:48f2dbca79a2)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
59694SScott.Rotondo@Sun.COM  * Common Development and Distribution License (the "License").
69694SScott.Rotondo@Sun.COM  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
21*13093SRoger.Faulkner@Oracle.COM 
220Sstevel@tonic-gate /*
23*13093SRoger.Faulkner@Oracle.COM  * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
24*13093SRoger.Faulkner@Oracle.COM  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
270Sstevel@tonic-gate /*	  All Rights Reserved  	*/
280Sstevel@tonic-gate 
290Sstevel@tonic-gate 
300Sstevel@tonic-gate /* Copyright (c) 1981 Regents of the University of California */
31802Scf46844 
320Sstevel@tonic-gate #include <stdio.h>	/* BUFSIZ: stdio = 1024, VMUNIX = 1024 */
330Sstevel@tonic-gate #ifndef TRACE
340Sstevel@tonic-gate #undef	NULL
350Sstevel@tonic-gate #endif
360Sstevel@tonic-gate 
370Sstevel@tonic-gate #include "ex.h"
380Sstevel@tonic-gate #include "ex_temp.h"
390Sstevel@tonic-gate #include "ex_tty.h"
400Sstevel@tonic-gate #include "ex_tune.h"
410Sstevel@tonic-gate #include <pwd.h>
420Sstevel@tonic-gate #include <locale.h>
430Sstevel@tonic-gate #include <dirent.h>
44634Sdp #include <unistd.h>
45634Sdp #include <errno.h>
46634Sdp 
470Sstevel@tonic-gate #define DIRSIZ	MAXNAMLEN
480Sstevel@tonic-gate 
490Sstevel@tonic-gate short tfile = -1;	/* ditto */
500Sstevel@tonic-gate 
510Sstevel@tonic-gate /*
520Sstevel@tonic-gate  *
530Sstevel@tonic-gate  * This program searches through the specified directory and then
540Sstevel@tonic-gate  * the directory usrpath(preserve) looking for an instance of the specified
550Sstevel@tonic-gate  * file from a crashed editor or a crashed system.
560Sstevel@tonic-gate  * If this file is found, it is unscrambled and written to
570Sstevel@tonic-gate  * the standard output.
580Sstevel@tonic-gate  *
590Sstevel@tonic-gate  * If this program terminates without a "broken pipe" diagnostic
600Sstevel@tonic-gate  * (i.e. the editor doesn't die right away) then the buffer we are
610Sstevel@tonic-gate  * writing from is removed when we finish.  This is potentially a mistake
620Sstevel@tonic-gate  * as there is not enough handshaking to guarantee that the file has actually
630Sstevel@tonic-gate  * been recovered, but should suffice for most cases.
640Sstevel@tonic-gate  */
650Sstevel@tonic-gate 
660Sstevel@tonic-gate /*
670Sstevel@tonic-gate  * This directory definition also appears (obviously) in expreserve.c.
680Sstevel@tonic-gate  * Change both if you change either.
690Sstevel@tonic-gate  */
700Sstevel@tonic-gate unsigned char	mydir[PATH_MAX+1];
710Sstevel@tonic-gate 
720Sstevel@tonic-gate /*
730Sstevel@tonic-gate  * Limit on the number of printed entries
740Sstevel@tonic-gate  * when an, e.g. ``ex -r'' command is given.
750Sstevel@tonic-gate  */
760Sstevel@tonic-gate #define	NENTRY	50
770Sstevel@tonic-gate 
780Sstevel@tonic-gate unsigned char	nb[BUFSIZE];
790Sstevel@tonic-gate int	vercnt;			/* Count number of versions of file found */
80802Scf46844 void rputfile(void);
81802Scf46844 void rsyserror(void);
82802Scf46844 void searchdir(unsigned char *);
83802Scf46844 void scrapbad(void);
84802Scf46844 void findtmp(unsigned char *);
85802Scf46844 void listfiles(unsigned char *);
86634Sdp 
87634Sdp int
main(int argc,char * argv[])88802Scf46844 main(int argc, char *argv[])
890Sstevel@tonic-gate {
900Sstevel@tonic-gate 	unsigned char string[50];
91802Scf46844 	unsigned char *cp;
92802Scf46844 	int c, b, i;
93802Scf46844 	int rflg = 0, errflg = 0;
940Sstevel@tonic-gate 	int label;
950Sstevel@tonic-gate 	line *tmpadr;
960Sstevel@tonic-gate 	extern unsigned char *mypass();
970Sstevel@tonic-gate 	struct passwd *pp = getpwuid(getuid());
980Sstevel@tonic-gate 	unsigned char rmcmd[PATH_MAX+1];
990Sstevel@tonic-gate 
1000Sstevel@tonic-gate 	(void)setlocale(LC_ALL, "");
1010Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
1020Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST"
1030Sstevel@tonic-gate #endif
1040Sstevel@tonic-gate 	(void)textdomain(TEXT_DOMAIN);
1050Sstevel@tonic-gate 	cp = string;
1060Sstevel@tonic-gate 	strcpy(mydir, USRPRESERVE);
1070Sstevel@tonic-gate 	if (pp == NULL) {
1080Sstevel@tonic-gate 		fprintf(stderr, gettext("Unable to get user's id\n"));
1090Sstevel@tonic-gate 		exit(-1);
1100Sstevel@tonic-gate 	}
1110Sstevel@tonic-gate 	strcat(mydir, pp->pw_name);
1120Sstevel@tonic-gate 
1130Sstevel@tonic-gate 	/*
1140Sstevel@tonic-gate 	 * Initialize as though the editor had just started.
1150Sstevel@tonic-gate 	 */
1160Sstevel@tonic-gate 	fendcore = (line *) sbrk(0);
1170Sstevel@tonic-gate 	dot = zero = dol = fendcore;
1180Sstevel@tonic-gate 	one = zero + 1;
1190Sstevel@tonic-gate 	endcore = fendcore - 2;
1200Sstevel@tonic-gate 	iblock = oblock = -1;
1210Sstevel@tonic-gate 
1220Sstevel@tonic-gate 	while ((c=getopt(argc, (char **)argv, "rx")) != EOF)
1230Sstevel@tonic-gate 		switch (c) {
1240Sstevel@tonic-gate 			case 'r':
1250Sstevel@tonic-gate 				rflg++;
1260Sstevel@tonic-gate 				break;
1270Sstevel@tonic-gate 
1280Sstevel@tonic-gate 			case 'x':
1290Sstevel@tonic-gate 				xflag++;
1300Sstevel@tonic-gate 				break;
1310Sstevel@tonic-gate 
1320Sstevel@tonic-gate 			case '?':
1330Sstevel@tonic-gate 				errflg++;
1340Sstevel@tonic-gate 				break;
1350Sstevel@tonic-gate 		}
1360Sstevel@tonic-gate 	argc -= optind;
1370Sstevel@tonic-gate 	argv = &argv[optind];
1380Sstevel@tonic-gate 
1390Sstevel@tonic-gate 	if (errflg)
1400Sstevel@tonic-gate 		exit(2);
1410Sstevel@tonic-gate 
1420Sstevel@tonic-gate 	/*
1430Sstevel@tonic-gate 	 * If given only a -r argument, then list the saved files.
1440Sstevel@tonic-gate 	 * (NOTE: single -r argument is scheduled to be replaced by -L).
1450Sstevel@tonic-gate 	 */
1460Sstevel@tonic-gate 	if (rflg && argc == 0) {
1470Sstevel@tonic-gate 		fprintf(stderr,"%s:\n", mydir);
1480Sstevel@tonic-gate 		listfiles(mydir);
1490Sstevel@tonic-gate 		fprintf(stderr,"%s:\n", TMPDIR);
150802Scf46844 		listfiles((unsigned char *)TMPDIR);
1510Sstevel@tonic-gate 		exit(0);
1520Sstevel@tonic-gate 	}
1530Sstevel@tonic-gate 
1540Sstevel@tonic-gate 	if (argc != 2)
1550Sstevel@tonic-gate 		error(gettext(" Wrong number of arguments to exrecover"), 0);
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate 	CP(file, argv[1]);
1580Sstevel@tonic-gate 
1590Sstevel@tonic-gate 	/*
1600Sstevel@tonic-gate 	 * Search for this file.
1610Sstevel@tonic-gate 	 */
162802Scf46844 	findtmp((unsigned char *)argv[0]);
1630Sstevel@tonic-gate 
1640Sstevel@tonic-gate 	/*
1650Sstevel@tonic-gate 	 * Got (one of the versions of) it, write it back to the editor.
1660Sstevel@tonic-gate 	 */
1670Sstevel@tonic-gate 	(void)cftime((char *)cp, "%a %h %d %T", &H.Time);
1680Sstevel@tonic-gate 	fprintf(stderr, vercnt > 1 ?
1690Sstevel@tonic-gate 		gettext(" [Dated: %s, newest of %d saved]") :
1700Sstevel@tonic-gate 		gettext(" [Dated: %s]"), cp, vercnt);
1710Sstevel@tonic-gate 	fprintf(stderr, "\r\n");
1720Sstevel@tonic-gate 
1730Sstevel@tonic-gate 	if(H.encrypted) {
1740Sstevel@tonic-gate 		if(xflag) {
1750Sstevel@tonic-gate 			kflag = run_setkey(perm, (unsigned char *)getenv("CrYpTkEy"));
1760Sstevel@tonic-gate 		} else
1770Sstevel@tonic-gate 			kflag = run_setkey(perm, mypass("Enter key:"));
1780Sstevel@tonic-gate 		if(kflag == -1) {
1790Sstevel@tonic-gate 			kflag = 0;
1800Sstevel@tonic-gate 			xflag = 0;
1810Sstevel@tonic-gate 			fprintf(stderr,gettext("Encryption facility not available\n"));
1820Sstevel@tonic-gate 			exit(-1);
1830Sstevel@tonic-gate 		}
1840Sstevel@tonic-gate                 xtflag = 1;
1850Sstevel@tonic-gate                 if (makekey(tperm) != 0) {
1860Sstevel@tonic-gate 			xtflag = 0;
1870Sstevel@tonic-gate 			fprintf(stderr,gettext("Warning--Cannot encrypt temporary buffer\n"));
1880Sstevel@tonic-gate 			exit(-1);
1890Sstevel@tonic-gate         	}
1900Sstevel@tonic-gate 	}
1910Sstevel@tonic-gate 	fprintf(stderr,gettext("\r\n [Hit return to continue]"));
1920Sstevel@tonic-gate 	fflush(stderr);
1930Sstevel@tonic-gate 	setbuf(stdin, (char *)NULL);
1940Sstevel@tonic-gate 	while((c = getchar()) != '\n' && c != '\r');
1950Sstevel@tonic-gate 	H.Flines++;
1960Sstevel@tonic-gate 
1970Sstevel@tonic-gate 	/*
1980Sstevel@tonic-gate 	 * Allocate space for the line pointers from the temp file.
1990Sstevel@tonic-gate 	 */
2000Sstevel@tonic-gate 	if ((int) sbrk((int) (H.Flines * sizeof (line))) == -1)
2010Sstevel@tonic-gate 		error(gettext(" Not enough core for lines"), 0);
2020Sstevel@tonic-gate #ifdef DEBUG
2030Sstevel@tonic-gate 	fprintf(stderr, "%d lines\n", H.Flines);
2040Sstevel@tonic-gate #endif
2050Sstevel@tonic-gate 
2060Sstevel@tonic-gate 	/*
2070Sstevel@tonic-gate 	 * Now go get the blocks of seek pointers which are scattered
2080Sstevel@tonic-gate 	 * throughout the temp file, reconstructing the incore
2090Sstevel@tonic-gate 	 * line pointers at point of crash.
2100Sstevel@tonic-gate 	 */
2110Sstevel@tonic-gate 	b = 0;
2120Sstevel@tonic-gate 	while (H.Flines > 0) {
2130Sstevel@tonic-gate 		(void)lseek(tfile, (long) blocks[b] * BUFSIZE, 0);
2140Sstevel@tonic-gate 		i = H.Flines < BUFSIZE / sizeof (line) ?
2150Sstevel@tonic-gate 			H.Flines * sizeof (line) : BUFSIZE;
2160Sstevel@tonic-gate 		if (read(tfile, (char *) dot, i) != i) {
2170Sstevel@tonic-gate 			perror((char *)nb);
2180Sstevel@tonic-gate 			exit(1);
2190Sstevel@tonic-gate 		}
2200Sstevel@tonic-gate 		dot += i / sizeof (line);
2210Sstevel@tonic-gate 		H.Flines -= i / sizeof (line);
2220Sstevel@tonic-gate 		b++;
2230Sstevel@tonic-gate 	}
2240Sstevel@tonic-gate 	dot--; dol = dot;
2250Sstevel@tonic-gate 
2260Sstevel@tonic-gate 	/*
2270Sstevel@tonic-gate 	 * Due to sandbagging some lines may really not be there.
2280Sstevel@tonic-gate 	 * Find and discard such.  This shouldn't happen often.
2290Sstevel@tonic-gate 	 */
2300Sstevel@tonic-gate 	scrapbad();
2310Sstevel@tonic-gate 
2320Sstevel@tonic-gate 
2330Sstevel@tonic-gate 	/*
2340Sstevel@tonic-gate 	 * Now if there were any lines in the recovered file
2350Sstevel@tonic-gate 	 * write them to the standard output.
2360Sstevel@tonic-gate 	 */
2370Sstevel@tonic-gate 	if (dol > zero) {
2380Sstevel@tonic-gate 		addr1 = one; addr2 = dol; io = 1;
239802Scf46844 		rputfile();
2400Sstevel@tonic-gate 	}
2410Sstevel@tonic-gate 	/*
2420Sstevel@tonic-gate 	 * Trash the saved buffer.
2430Sstevel@tonic-gate 	 * Hopefully the system won't crash before the editor
2440Sstevel@tonic-gate 	 * syncs the new recovered buffer; i.e. for an instant here
2450Sstevel@tonic-gate 	 * you may lose if the system crashes because this file
2460Sstevel@tonic-gate 	 * is gone, but the editor hasn't completed reading the recovered
2470Sstevel@tonic-gate 	 * file from the pipe from us to it.
2480Sstevel@tonic-gate 	 *
2490Sstevel@tonic-gate 	 * This doesn't work if we are coming from an non-absolute path
2500Sstevel@tonic-gate 	 * name since we may have chdir'ed but what the hay, noone really
2510Sstevel@tonic-gate 	 * ever edits with temporaries in "." anyways.
2520Sstevel@tonic-gate 	 */
2530Sstevel@tonic-gate 	if (nb[0] == '/') {
254634Sdp 		(void)unlink((const char *)nb);
2550Sstevel@tonic-gate 		sprintf((char *)rmcmd, "rmdir %s 2> /dev/null", (char *)mydir);
2560Sstevel@tonic-gate 		system((char *)rmcmd);
2570Sstevel@tonic-gate 	}
258802Scf46844 	return (0);
2590Sstevel@tonic-gate }
2600Sstevel@tonic-gate 
2610Sstevel@tonic-gate /*
2620Sstevel@tonic-gate  * Print an error message (notably not in error
2630Sstevel@tonic-gate  * message file).  If terminal is in RAW mode, then
2640Sstevel@tonic-gate  * we should be writing output for "vi", so don't print
2650Sstevel@tonic-gate  * a newline which would mess up the screen.
2660Sstevel@tonic-gate  */
2670Sstevel@tonic-gate /*VARARGS2*/
268802Scf46844 void
error(str,inf)2690Sstevel@tonic-gate error(str, inf)
2700Sstevel@tonic-gate 	unsigned char *str;
2710Sstevel@tonic-gate 	int inf;
2720Sstevel@tonic-gate {
2730Sstevel@tonic-gate 
2740Sstevel@tonic-gate 	struct termio termio;
2750Sstevel@tonic-gate 	if (inf)
2760Sstevel@tonic-gate 		fprintf(stderr, (char *)str, inf);
2770Sstevel@tonic-gate 	else
2780Sstevel@tonic-gate 		fprintf(stderr, (char *)str);
2790Sstevel@tonic-gate 
2800Sstevel@tonic-gate 	ioctl(2, TCGETA, &termio);
2810Sstevel@tonic-gate 	if (termio.c_lflag & ICANON)
2820Sstevel@tonic-gate 		fprintf(stderr, "\n");
2830Sstevel@tonic-gate 	exit(1);
2840Sstevel@tonic-gate }
2850Sstevel@tonic-gate 
2860Sstevel@tonic-gate /*
2870Sstevel@tonic-gate  * Here we save the information about files, when
2880Sstevel@tonic-gate  * you ask us what files we have saved for you.
2890Sstevel@tonic-gate  * We buffer file name, number of lines, and the time
2900Sstevel@tonic-gate  * at which the file was saved.
2910Sstevel@tonic-gate  */
2920Sstevel@tonic-gate struct svfile {
2930Sstevel@tonic-gate 	unsigned char	sf_name[FNSIZE + 1];
2940Sstevel@tonic-gate 	int	sf_lines;
2950Sstevel@tonic-gate 	unsigned char	sf_entry[DIRSIZ + 1];
2960Sstevel@tonic-gate 	time_t	sf_time;
2970Sstevel@tonic-gate 	short	sf_encrypted;
2980Sstevel@tonic-gate };
299802Scf46844 void enter(struct svfile *, unsigned char *, int);
3000Sstevel@tonic-gate 
301802Scf46844 void
listfiles(unsigned char * dirname)302802Scf46844 listfiles(unsigned char *dirname)
3030Sstevel@tonic-gate {
304802Scf46844 	DIR *dir;
3050Sstevel@tonic-gate 	struct dirent64 *direntry;
3060Sstevel@tonic-gate 	int ecount, qucmp();
307802Scf46844 	int f;
3080Sstevel@tonic-gate 	unsigned char cp[50];
3090Sstevel@tonic-gate 	unsigned char cp2[50];
3100Sstevel@tonic-gate 	unsigned char *filname;
3110Sstevel@tonic-gate 	struct svfile *fp, svbuf[NENTRY];
3120Sstevel@tonic-gate 
3130Sstevel@tonic-gate 	/*
3140Sstevel@tonic-gate 	 * Open usrpath(preserve), and go there to make things quick.
3150Sstevel@tonic-gate 	 */
3160Sstevel@tonic-gate 	if ((dir = opendir((char *)dirname)) == NULL)
3170Sstevel@tonic-gate 	{
3180Sstevel@tonic-gate 		fprintf(stderr,gettext("No files saved.\n"));
3190Sstevel@tonic-gate 		return;
3200Sstevel@tonic-gate 	}
321634Sdp 	if (chdir((const char *)dirname) < 0) {
3220Sstevel@tonic-gate 		perror((char *)dirname);
3230Sstevel@tonic-gate 		return;
3240Sstevel@tonic-gate 	}
3250Sstevel@tonic-gate 
3260Sstevel@tonic-gate 	/*
3270Sstevel@tonic-gate 	 * Look at the candidate files in usrpath(preserve).
3280Sstevel@tonic-gate 	 */
3290Sstevel@tonic-gate 	fp = &svbuf[0];
3300Sstevel@tonic-gate 	ecount = 0;
3310Sstevel@tonic-gate 	while ((direntry = readdir64(dir)) != NULL)
3320Sstevel@tonic-gate 	{
3330Sstevel@tonic-gate 		filname = (unsigned char *)direntry->d_name;
3340Sstevel@tonic-gate 		if (filname[0] != 'E')
3350Sstevel@tonic-gate 			continue;
3360Sstevel@tonic-gate #ifdef DEBUG
3370Sstevel@tonic-gate 		fprintf(stderr, "considering %s\n", filname);
3380Sstevel@tonic-gate #endif
3390Sstevel@tonic-gate 		/*
3400Sstevel@tonic-gate 		 * Name begins with E; open it and
3410Sstevel@tonic-gate 		 * make sure the uid in the header is our uid.
3420Sstevel@tonic-gate 		 * If not, then don't bother with this file, it can't
3430Sstevel@tonic-gate 		 * be ours.
3440Sstevel@tonic-gate 		 */
3450Sstevel@tonic-gate 		f = open(filname, 0);
3460Sstevel@tonic-gate 		if (f < 0) {
3470Sstevel@tonic-gate #ifdef DEBUG
3480Sstevel@tonic-gate 			fprintf(stderr, "open failed\n");
3490Sstevel@tonic-gate #endif
3500Sstevel@tonic-gate 			continue;
3510Sstevel@tonic-gate 		}
3520Sstevel@tonic-gate 		if (read(f, (char *) &H, sizeof H) != sizeof H) {
3530Sstevel@tonic-gate #ifdef DEBUG
3540Sstevel@tonic-gate 			fprintf(stderr, "could not read header\n");
3550Sstevel@tonic-gate #endif
3560Sstevel@tonic-gate 			(void)close(f);
3570Sstevel@tonic-gate 			continue;
3580Sstevel@tonic-gate 		}
3590Sstevel@tonic-gate 		(void)close(f);
3600Sstevel@tonic-gate 		if (getuid() != H.Uid) {
3610Sstevel@tonic-gate #ifdef DEBUG
3620Sstevel@tonic-gate 			fprintf(stderr, "uid wrong\n");
3630Sstevel@tonic-gate #endif
3640Sstevel@tonic-gate 			continue;
3650Sstevel@tonic-gate 		}
3660Sstevel@tonic-gate 
3670Sstevel@tonic-gate 		/*
3680Sstevel@tonic-gate 		 * Saved the day!
3690Sstevel@tonic-gate 		 */
3700Sstevel@tonic-gate 		enter(fp++, filname, ecount);
3710Sstevel@tonic-gate 		ecount++;
3720Sstevel@tonic-gate #ifdef DEBUG
3730Sstevel@tonic-gate 		fprintf(stderr, "entered file %s\n", filname);
3740Sstevel@tonic-gate #endif
3750Sstevel@tonic-gate 	}
3760Sstevel@tonic-gate 	(void)closedir(dir);
3770Sstevel@tonic-gate 	/*
3780Sstevel@tonic-gate 	 * If any files were saved, then sort them and print
3790Sstevel@tonic-gate 	 * them out.
3800Sstevel@tonic-gate 	 */
3810Sstevel@tonic-gate 	if (ecount == 0) {
3820Sstevel@tonic-gate 		fprintf(stderr, gettext("No files saved.\n"));
3830Sstevel@tonic-gate 		return;
3840Sstevel@tonic-gate 	}
3850Sstevel@tonic-gate 	qsort(&svbuf[0], ecount, sizeof svbuf[0], qucmp);
3860Sstevel@tonic-gate 	for (fp = &svbuf[0]; fp < &svbuf[ecount]; fp++) {
3870Sstevel@tonic-gate 		(void)cftime((char *)cp, "%a %b %d", &fp->sf_time);
3880Sstevel@tonic-gate 		(void)cftime((char *)cp2, "%R", &fp->sf_time);
3890Sstevel@tonic-gate 		fprintf(stderr,
3900Sstevel@tonic-gate 		    gettext("On %s at %s, saved %d lines of file \"%s\" "),
3910Sstevel@tonic-gate 		    cp, cp2, fp->sf_lines, fp->sf_name);
3920Sstevel@tonic-gate 		fprintf(stderr, "%s\n",
3930Sstevel@tonic-gate 		    (fp->sf_encrypted) ? gettext("[ENCRYPTED]") : "");
3940Sstevel@tonic-gate 	}
3950Sstevel@tonic-gate }
3960Sstevel@tonic-gate 
3970Sstevel@tonic-gate /*
3980Sstevel@tonic-gate  * Enter a new file into the saved file information.
3990Sstevel@tonic-gate  */
400802Scf46844 void
enter(struct svfile * fp,unsigned char * fname,int count)401802Scf46844 enter(struct svfile *fp, unsigned char *fname, int count)
4020Sstevel@tonic-gate {
403802Scf46844 	unsigned char *cp, *cp2;
404802Scf46844 	struct svfile *f, *fl;
4050Sstevel@tonic-gate 	time_t curtime;
4060Sstevel@tonic-gate 
4070Sstevel@tonic-gate 	f = 0;
4080Sstevel@tonic-gate 	if (count >= NENTRY) {
4090Sstevel@tonic-gate 	        /*
4100Sstevel@tonic-gate 		 * Trash the oldest as the most useless.
4110Sstevel@tonic-gate 		 */
4120Sstevel@tonic-gate 		fl = fp - count + NENTRY - 1;
4130Sstevel@tonic-gate 		curtime = fl->sf_time;
4140Sstevel@tonic-gate 		for (f = fl; --f > fp-count; )
4150Sstevel@tonic-gate 			if (f->sf_time < curtime)
4160Sstevel@tonic-gate 				curtime = f->sf_time;
4170Sstevel@tonic-gate 		for (f = fl; --f > fp-count; )
4180Sstevel@tonic-gate 			if (f->sf_time == curtime)
4190Sstevel@tonic-gate 				break;
4200Sstevel@tonic-gate 		fp = f;
4210Sstevel@tonic-gate 	}
4220Sstevel@tonic-gate 
4230Sstevel@tonic-gate 	/*
4240Sstevel@tonic-gate 	 * Gotcha.
4250Sstevel@tonic-gate 	 */
4260Sstevel@tonic-gate 	fp->sf_time = H.Time;
4270Sstevel@tonic-gate 	fp->sf_lines = H.Flines;
4280Sstevel@tonic-gate 	fp->sf_encrypted = H.encrypted;
4290Sstevel@tonic-gate 	for (cp2 = fp->sf_name, cp = savedfile; *cp;)
4300Sstevel@tonic-gate 		*cp2++ = *cp++;
4310Sstevel@tonic-gate 	*cp2++ = 0;
4320Sstevel@tonic-gate 	for (cp2 = fp->sf_entry, cp = fname; *cp && cp-fname < 14;)
4330Sstevel@tonic-gate 		*cp2++ = *cp++;
4340Sstevel@tonic-gate 	*cp2++ = 0;
4350Sstevel@tonic-gate }
4360Sstevel@tonic-gate 
4370Sstevel@tonic-gate /*
4380Sstevel@tonic-gate  * Do the qsort compare to sort the entries first by file name,
4390Sstevel@tonic-gate  * then by modify time.
4400Sstevel@tonic-gate  */
441802Scf46844 int
qucmp(struct svfile * p1,struct svfile * p2)442802Scf46844 qucmp(struct svfile *p1, struct svfile *p2)
4430Sstevel@tonic-gate {
444802Scf46844 	int t;
4450Sstevel@tonic-gate 
4460Sstevel@tonic-gate 	if (t = strcmp(p1->sf_name, p2->sf_name))
4470Sstevel@tonic-gate 		return(t);
4480Sstevel@tonic-gate 	if (p1->sf_time > p2->sf_time)
4490Sstevel@tonic-gate 		return(-1);
4500Sstevel@tonic-gate 	return(p1->sf_time < p2->sf_time);
4510Sstevel@tonic-gate }
4520Sstevel@tonic-gate 
4530Sstevel@tonic-gate /*
4540Sstevel@tonic-gate  * Scratch for search.
4550Sstevel@tonic-gate  */
4560Sstevel@tonic-gate unsigned char	bestnb[BUFSIZE];		/* Name of the best one */
4570Sstevel@tonic-gate long	besttime = 0;		/* Time at which the best file was saved */
4580Sstevel@tonic-gate int	bestfd;			/* Keep best file open so it dont vanish */
4590Sstevel@tonic-gate 
4600Sstevel@tonic-gate /*
4610Sstevel@tonic-gate  * Look for a file, both in the users directory option value
4620Sstevel@tonic-gate  * (i.e. usually /tmp) and in usrpath(preserve).
4630Sstevel@tonic-gate  * Want to find the newest so we search on and on.
4640Sstevel@tonic-gate  */
465802Scf46844 void
findtmp(unsigned char * dir)466802Scf46844 findtmp(unsigned char *dir)
4670Sstevel@tonic-gate {
4680Sstevel@tonic-gate 
4690Sstevel@tonic-gate 	/*
4700Sstevel@tonic-gate 	 * No name or file so far.
4710Sstevel@tonic-gate 	 */
4720Sstevel@tonic-gate 	bestnb[0] = 0;
4730Sstevel@tonic-gate 	bestfd = -1;
4740Sstevel@tonic-gate 
4750Sstevel@tonic-gate 	/*
4760Sstevel@tonic-gate 	 * Search usrpath(preserve) and, if we can get there, /tmp
4770Sstevel@tonic-gate 	 * (actually the user's "directory" option).
4780Sstevel@tonic-gate 	 */
4790Sstevel@tonic-gate 	searchdir(dir);
480634Sdp 	if (chdir((const char *)mydir) == 0)
4810Sstevel@tonic-gate 		searchdir(mydir);
4820Sstevel@tonic-gate 	if (bestfd != -1) {
4830Sstevel@tonic-gate 		/*
4840Sstevel@tonic-gate 		 * Gotcha.
4850Sstevel@tonic-gate 		 * Put the file (which is already open) in the file
4860Sstevel@tonic-gate 		 * used by the temp file routines, and save its
4870Sstevel@tonic-gate 		 * name for later unlinking.
4880Sstevel@tonic-gate 		 */
4890Sstevel@tonic-gate 		tfile = bestfd;
4900Sstevel@tonic-gate 		CP(nb, bestnb);
4910Sstevel@tonic-gate 		(void)lseek(tfile, 0l, 0);
4920Sstevel@tonic-gate 
4930Sstevel@tonic-gate 		/*
4940Sstevel@tonic-gate 		 * Gotta be able to read the header or fall through
4950Sstevel@tonic-gate 		 * to lossage.
4960Sstevel@tonic-gate 		 */
4970Sstevel@tonic-gate 		if (read(tfile, (char *) &H, sizeof H) == sizeof H)
4980Sstevel@tonic-gate 			return;
4990Sstevel@tonic-gate 	}
5000Sstevel@tonic-gate 
5010Sstevel@tonic-gate 	/*
5020Sstevel@tonic-gate 	 * Extreme lossage...
5030Sstevel@tonic-gate 	 */
504802Scf46844 	error((unsigned char *)gettext(" File not found"), 0);
5050Sstevel@tonic-gate }
5060Sstevel@tonic-gate 
5070Sstevel@tonic-gate /*
5080Sstevel@tonic-gate  * Search for the file in directory dirname.
5090Sstevel@tonic-gate  *
5100Sstevel@tonic-gate  * Don't chdir here, because the users directory
5110Sstevel@tonic-gate  * may be ".", and we would move away before we searched it.
5120Sstevel@tonic-gate  * Note that we actually chdir elsewhere (because it is too slow
5130Sstevel@tonic-gate  * to look around in usrpath(preserve) without chdir'ing there) so we
5140Sstevel@tonic-gate  * can't win, because we don't know the name of '.' and if the path
5150Sstevel@tonic-gate  * name of the file we want to unlink is relative, rather than absolute
5160Sstevel@tonic-gate  * we won't be able to find it again.
5170Sstevel@tonic-gate  */
518802Scf46844 void
searchdir(unsigned char * dirname)519802Scf46844 searchdir(unsigned char *dirname)
5200Sstevel@tonic-gate {
5210Sstevel@tonic-gate 	struct dirent64 *direntry;
522802Scf46844 	DIR *dir;
5230Sstevel@tonic-gate 	unsigned char dbuf[BUFSIZE];
5240Sstevel@tonic-gate 	unsigned char *filname;
5250Sstevel@tonic-gate 	if ((dir = opendir((char *)dirname)) == NULL)
5260Sstevel@tonic-gate 		return;
5270Sstevel@tonic-gate 	while ((direntry = readdir64(dir)) != NULL)
5280Sstevel@tonic-gate 	{
5290Sstevel@tonic-gate 		filname = (unsigned char *)direntry->d_name;
5300Sstevel@tonic-gate 		if (filname[0] != 'E' || filname[1] != 'x')
5310Sstevel@tonic-gate 			continue;
5320Sstevel@tonic-gate 		/*
5330Sstevel@tonic-gate 		 * Got a file in the directory starting with Ex...
5340Sstevel@tonic-gate 		 * Save a consed up name for the file to unlink
5350Sstevel@tonic-gate 		 * later, and check that this is really a file
5360Sstevel@tonic-gate 		 * we are looking for.
5370Sstevel@tonic-gate 		 */
5380Sstevel@tonic-gate 		(void)strcat(strcat(strcpy(nb, dirname), "/"), filname);
5390Sstevel@tonic-gate 		if (yeah(nb)) {
5400Sstevel@tonic-gate 			/*
5410Sstevel@tonic-gate 			 * Well, it is the file we are looking for.
5420Sstevel@tonic-gate 			 * Is it more recent than any version we found before?
5430Sstevel@tonic-gate 			 */
5440Sstevel@tonic-gate 			if (H.Time > besttime) {
5450Sstevel@tonic-gate 				/*
5460Sstevel@tonic-gate 				 * A winner.
5470Sstevel@tonic-gate 				 */
5480Sstevel@tonic-gate 				(void)close(bestfd);
5490Sstevel@tonic-gate 				bestfd = dup(tfile);
5500Sstevel@tonic-gate 				besttime = H.Time;
5510Sstevel@tonic-gate 				CP(bestnb, nb);
5520Sstevel@tonic-gate 			}
5530Sstevel@tonic-gate 			/*
5540Sstevel@tonic-gate 			 * Count versions and tell user
5550Sstevel@tonic-gate 			 */
5560Sstevel@tonic-gate 			vercnt++;
5570Sstevel@tonic-gate 		}
5580Sstevel@tonic-gate 		(void)close(tfile);
5590Sstevel@tonic-gate 	}
5600Sstevel@tonic-gate 	(void)closedir(dir);
5610Sstevel@tonic-gate }
5620Sstevel@tonic-gate 
5630Sstevel@tonic-gate /*
5640Sstevel@tonic-gate  * Given a candidate file to be recovered, see
5650Sstevel@tonic-gate  * if it's really an editor temporary and of this
5660Sstevel@tonic-gate  * user and the file specified.
5670Sstevel@tonic-gate  */
568802Scf46844 int
yeah(unsigned char * name)569802Scf46844 yeah(unsigned char *name)
5700Sstevel@tonic-gate {
5710Sstevel@tonic-gate 
5720Sstevel@tonic-gate 	tfile = open(name, 2);
5730Sstevel@tonic-gate 	if (tfile < 0)
5740Sstevel@tonic-gate 		return (0);
5750Sstevel@tonic-gate 	if (read(tfile, (char *) &H, sizeof H) != sizeof H) {
5760Sstevel@tonic-gate nope:
5770Sstevel@tonic-gate 		(void)close(tfile);
5780Sstevel@tonic-gate 		return (0);
5790Sstevel@tonic-gate 	}
5800Sstevel@tonic-gate 	if (!eq(savedfile, file))
5810Sstevel@tonic-gate 		goto nope;
5820Sstevel@tonic-gate 	if (getuid() != H.Uid)
5830Sstevel@tonic-gate 		goto nope;
5840Sstevel@tonic-gate 	/*
5850Sstevel@tonic-gate 	 * Old code: puts a word LOST in the header block, so that lost lines
5860Sstevel@tonic-gate 	 * can be made to point at it.
5870Sstevel@tonic-gate 	 */
5880Sstevel@tonic-gate 	(void)lseek(tfile, (long)(BUFSIZE*HBLKS-8), 0);
5890Sstevel@tonic-gate 	(void)write(tfile, "LOST", 5);
5900Sstevel@tonic-gate 	return (1);
5910Sstevel@tonic-gate }
5920Sstevel@tonic-gate 
5930Sstevel@tonic-gate /*
5940Sstevel@tonic-gate  * Find the true end of the scratch file, and ``LOSE''
5950Sstevel@tonic-gate  * lines which point into thin air.  This lossage occurs
5960Sstevel@tonic-gate  * due to the sandbagging of i/o which can cause blocks to
5970Sstevel@tonic-gate  * be written in a non-obvious order, different from the order
5980Sstevel@tonic-gate  * in which the editor tried to write them.
5990Sstevel@tonic-gate  *
6000Sstevel@tonic-gate  * Lines which are lost are replaced with the text LOST so
6010Sstevel@tonic-gate  * they are easy to find.  We work hard at pretty formatting here
6020Sstevel@tonic-gate  * as lines tend to be lost in blocks.
6030Sstevel@tonic-gate  *
6040Sstevel@tonic-gate  * This only seems to happen on very heavily loaded systems, and
6050Sstevel@tonic-gate  * not very often.
6060Sstevel@tonic-gate  */
607802Scf46844 void
scrapbad(void)608802Scf46844 scrapbad(void)
6090Sstevel@tonic-gate {
610802Scf46844 	line *ip;
6110Sstevel@tonic-gate 	struct stat64 stbuf;
6120Sstevel@tonic-gate 	off_t size, maxt;
6130Sstevel@tonic-gate 	int bno, cnt, bad, was;
6140Sstevel@tonic-gate 	unsigned char bk[BUFSIZE];
6150Sstevel@tonic-gate 
6160Sstevel@tonic-gate 	(void)fstat64(tfile, &stbuf);
6170Sstevel@tonic-gate 	size = (off_t)stbuf.st_size;
6180Sstevel@tonic-gate 	maxt = (size >> SHFT) | (BNDRY-1);
6190Sstevel@tonic-gate 	bno = (maxt >> OFFBTS) & BLKMSK;
6200Sstevel@tonic-gate #ifdef DEBUG
6210Sstevel@tonic-gate 	fprintf(stderr, "size %ld, maxt %o, bno %d\n", size, maxt, bno);
6220Sstevel@tonic-gate #endif
6230Sstevel@tonic-gate 
6240Sstevel@tonic-gate 	/*
6250Sstevel@tonic-gate 	 * Look for a null separating two lines in the temp file;
6260Sstevel@tonic-gate 	 * if last line was split across blocks, then it is lost
6270Sstevel@tonic-gate 	 * if the last block is.
6280Sstevel@tonic-gate 	 */
6290Sstevel@tonic-gate 	while (bno > 0) {
6300Sstevel@tonic-gate 		(void)lseek(tfile, (long) BUFSIZE * bno, 0);
6310Sstevel@tonic-gate 		cnt = read(tfile, (char *) bk, BUFSIZE);
6320Sstevel@tonic-gate 	if(xtflag)
6330Sstevel@tonic-gate 		if (run_crypt(0L, bk, CRSIZE, tperm) == -1)
634802Scf46844 		    rsyserror();
6350Sstevel@tonic-gate #ifdef DEBUG
6360Sstevel@tonic-gate 	fprintf(stderr,"UNENCRYPTED: BLK %d\n",bno);
6370Sstevel@tonic-gate #endif
6380Sstevel@tonic-gate 		while (cnt > 0)
6390Sstevel@tonic-gate 			if (bk[--cnt] == 0)
6400Sstevel@tonic-gate 				goto null;
6410Sstevel@tonic-gate 		bno--;
6420Sstevel@tonic-gate 	}
6430Sstevel@tonic-gate null:
6440Sstevel@tonic-gate 
6450Sstevel@tonic-gate 	/*
6460Sstevel@tonic-gate 	 * Magically calculate the largest valid pointer in the temp file,
6470Sstevel@tonic-gate 	 * consing it up from the block number and the count.
6480Sstevel@tonic-gate 	 */
6490Sstevel@tonic-gate 	maxt = ((bno << OFFBTS) | (cnt >> SHFT)) & ~1;
6500Sstevel@tonic-gate #ifdef DEBUG
6510Sstevel@tonic-gate 	fprintf(stderr, "bno %d, cnt %d, maxt %o\n", bno, cnt, maxt);
6520Sstevel@tonic-gate #endif
6530Sstevel@tonic-gate 
6540Sstevel@tonic-gate 	/*
6550Sstevel@tonic-gate 	 * Now cycle through the line pointers,
6560Sstevel@tonic-gate 	 * trashing the Lusers.
6570Sstevel@tonic-gate 	 */
6580Sstevel@tonic-gate 	was = bad = 0;
6590Sstevel@tonic-gate 	for (ip = one; ip <= dol; ip++)
6600Sstevel@tonic-gate 		if (*ip > maxt) {
6610Sstevel@tonic-gate #ifdef DEBUG
6620Sstevel@tonic-gate 			fprintf(stderr, "%d bad, %o > %o\n", ip - zero, *ip, maxt);
6630Sstevel@tonic-gate #endif
6640Sstevel@tonic-gate 			if (was == 0)
6650Sstevel@tonic-gate 				was = ip - zero;
6660Sstevel@tonic-gate 			*ip = ((HBLKS*BUFSIZE)-8) >> SHFT;
6670Sstevel@tonic-gate 		} else if (was) {
6680Sstevel@tonic-gate 			if (bad == 0)
6690Sstevel@tonic-gate 				fprintf(stderr, gettext(" [Lost line(s):"));
6700Sstevel@tonic-gate 			fprintf(stderr, " %d", was);
6710Sstevel@tonic-gate 			if ((ip - 1) - zero > was)
6720Sstevel@tonic-gate 				fprintf(stderr, "-%d", (ip - 1) - zero);
6730Sstevel@tonic-gate 			bad++;
6740Sstevel@tonic-gate 			was = 0;
6750Sstevel@tonic-gate 		}
6760Sstevel@tonic-gate 	if (was != 0) {
6770Sstevel@tonic-gate 		if (bad == 0)
6780Sstevel@tonic-gate 			fprintf(stderr, " [Lost line(s):");
6790Sstevel@tonic-gate 		fprintf(stderr, " %d", was);
6800Sstevel@tonic-gate 		if (dol - zero != was)
6810Sstevel@tonic-gate 			fprintf(stderr, "-%d", dol - zero);
6820Sstevel@tonic-gate 		bad++;
6830Sstevel@tonic-gate 	}
6840Sstevel@tonic-gate 	if (bad)
6850Sstevel@tonic-gate 		fprintf(stderr, "]");
6860Sstevel@tonic-gate }
6870Sstevel@tonic-gate 
6880Sstevel@tonic-gate int	cntch, cntln, cntodd, cntnull;
6890Sstevel@tonic-gate /*
6900Sstevel@tonic-gate  * Following routines stolen mercilessly from ex.
6910Sstevel@tonic-gate  */
692802Scf46844 void
rputfile(void)693802Scf46844 rputfile(void)
6940Sstevel@tonic-gate {
6950Sstevel@tonic-gate 	line *a1;
696802Scf46844 	unsigned char *fp, *lp;
697802Scf46844 	int nib;
6980Sstevel@tonic-gate 
6990Sstevel@tonic-gate 	a1 = addr1;
7000Sstevel@tonic-gate 	clrstats();
7010Sstevel@tonic-gate 	cntln = addr2 - a1 + 1;
7020Sstevel@tonic-gate 	if (cntln == 0)
7030Sstevel@tonic-gate 		return;
7040Sstevel@tonic-gate 	nib = BUFSIZE;
7050Sstevel@tonic-gate 	fp = genbuf;
7060Sstevel@tonic-gate 	do {
7070Sstevel@tonic-gate #ifdef DEBUG
7080Sstevel@tonic-gate 		fprintf(stderr,"GETTING A LINE \n");
7090Sstevel@tonic-gate #endif
710*13093SRoger.Faulkner@Oracle.COM 		getaline(*a1++);
7110Sstevel@tonic-gate 		lp = linebuf;
7120Sstevel@tonic-gate #ifdef DEBUG
7130Sstevel@tonic-gate 		fprintf(stderr,"LINE:%s\n",linebuf);
7140Sstevel@tonic-gate #endif
7150Sstevel@tonic-gate 		for (;;) {
7160Sstevel@tonic-gate 			if (--nib < 0) {
7170Sstevel@tonic-gate 				nib = fp - genbuf;
7180Sstevel@tonic-gate 				if (write(io, genbuf, nib) != nib)
7190Sstevel@tonic-gate 					wrerror();
7200Sstevel@tonic-gate 				cntch += nib;
7210Sstevel@tonic-gate 				nib = BUFSIZE;
7220Sstevel@tonic-gate 				fp = genbuf;
7230Sstevel@tonic-gate 			}
7240Sstevel@tonic-gate 			if ((*fp++ = *lp++) == 0) {
7250Sstevel@tonic-gate 				fp[-1] = '\n';
7260Sstevel@tonic-gate 				break;
7270Sstevel@tonic-gate 			}
7280Sstevel@tonic-gate 		}
7290Sstevel@tonic-gate 	} while (a1 <= addr2);
7300Sstevel@tonic-gate 	nib = fp - genbuf;
7310Sstevel@tonic-gate 	if (write(io, genbuf, nib) != nib)
7320Sstevel@tonic-gate 		wrerror();
7330Sstevel@tonic-gate 	cntch += nib;
7340Sstevel@tonic-gate }
7350Sstevel@tonic-gate 
736802Scf46844 void
wrerror(void)737802Scf46844 wrerror(void)
7380Sstevel@tonic-gate {
7390Sstevel@tonic-gate 
740802Scf46844 	rsyserror();
7410Sstevel@tonic-gate }
7420Sstevel@tonic-gate 
743802Scf46844 void
clrstats(void)744802Scf46844 clrstats(void)
7450Sstevel@tonic-gate {
7460Sstevel@tonic-gate 
7470Sstevel@tonic-gate 	ninbuf = 0;
7480Sstevel@tonic-gate 	cntch = 0;
7490Sstevel@tonic-gate 	cntln = 0;
7500Sstevel@tonic-gate 	cntnull = 0;
7510Sstevel@tonic-gate 	cntodd = 0;
7520Sstevel@tonic-gate }
7530Sstevel@tonic-gate 
7540Sstevel@tonic-gate #define	READ	0
7550Sstevel@tonic-gate #define	WRITE	1
7560Sstevel@tonic-gate 
757802Scf46844 void
getaline(line tl)758*13093SRoger.Faulkner@Oracle.COM getaline(line tl)
7590Sstevel@tonic-gate {
760802Scf46844 	unsigned char *bp, *lp;
761802Scf46844 	int nl;
7620Sstevel@tonic-gate 
7630Sstevel@tonic-gate 	lp = linebuf;
7640Sstevel@tonic-gate 	bp = getblock(tl);
7650Sstevel@tonic-gate 	nl = nleft;
7660Sstevel@tonic-gate 	tl &= ~OFFMSK;
7670Sstevel@tonic-gate 	while (*lp++ = *bp++)
7680Sstevel@tonic-gate 		if (--nl == 0) {
7690Sstevel@tonic-gate 			bp = getblock(tl += INCRMT);
7700Sstevel@tonic-gate 			nl = nleft;
7710Sstevel@tonic-gate 		}
7720Sstevel@tonic-gate }
7730Sstevel@tonic-gate 
7740Sstevel@tonic-gate int	read();
7750Sstevel@tonic-gate int	write();
7760Sstevel@tonic-gate 
7770Sstevel@tonic-gate unsigned char *
getblock(atl)7780Sstevel@tonic-gate getblock(atl)
7790Sstevel@tonic-gate 	line atl;
7800Sstevel@tonic-gate {
781802Scf46844 	int bno, off;
782802Scf46844         unsigned char *p1, *p2;
783802Scf46844         int n;
7840Sstevel@tonic-gate 
7850Sstevel@tonic-gate 	bno = (atl >> OFFBTS) & BLKMSK;
7860Sstevel@tonic-gate #ifdef DEBUG
7870Sstevel@tonic-gate 	fprintf(stderr,"GETBLOCK: BLK %d\n",bno);
7880Sstevel@tonic-gate #endif
7890Sstevel@tonic-gate 	off = (atl << SHFT) & LBTMSK;
7900Sstevel@tonic-gate 	if (bno >= NMBLKS)
791802Scf46844 		error((unsigned char *)gettext(" Tmp file too large"));
7920Sstevel@tonic-gate 	nleft = BUFSIZE - off;
7930Sstevel@tonic-gate 	if (bno == iblock)
7940Sstevel@tonic-gate 		return (ibuff + off);
7950Sstevel@tonic-gate 	iblock = bno;
7960Sstevel@tonic-gate 	blkio(bno, ibuff, read);
7970Sstevel@tonic-gate 	if(xtflag)
7980Sstevel@tonic-gate 		if (run_crypt(0L, ibuff, CRSIZE, tperm) == -1)
799802Scf46844 		    rsyserror();
8000Sstevel@tonic-gate #ifdef DEBUG
8010Sstevel@tonic-gate 	fprintf(stderr,"UNENCRYPTED: BLK %d\n",bno);
8020Sstevel@tonic-gate #endif
8030Sstevel@tonic-gate 	return (ibuff + off);
8040Sstevel@tonic-gate }
8050Sstevel@tonic-gate 
806802Scf46844 void
blkio(short b,unsigned char * buf,int (* iofcn)())807802Scf46844 blkio(short b, unsigned char *buf, int (*iofcn)())
8080Sstevel@tonic-gate {
8090Sstevel@tonic-gate 
8100Sstevel@tonic-gate 	int rc;
8110Sstevel@tonic-gate 	lseek(tfile, (long) (unsigned) b * BUFSIZE, 0);
8120Sstevel@tonic-gate 	if ((rc =(*iofcn)(tfile, buf, BUFSIZE)) != BUFSIZE) {
8130Sstevel@tonic-gate 		(void)fprintf(stderr,gettext("Failed on BLK: %d with %d/%d\n"),b,rc,BUFSIZE);
8140Sstevel@tonic-gate 		perror("");
815802Scf46844 		rsyserror();
8160Sstevel@tonic-gate 	}
8170Sstevel@tonic-gate }
8180Sstevel@tonic-gate 
819802Scf46844 void
rsyserror(void)820802Scf46844 rsyserror(void)
8210Sstevel@tonic-gate {
822634Sdp 	int save_err = errno;
8230Sstevel@tonic-gate 
8240Sstevel@tonic-gate 	dirtcnt = 0;
8250Sstevel@tonic-gate 	write(2, " ", 1);
826634Sdp 	error(strerror(save_err));
8270Sstevel@tonic-gate 	exit(1);
8280Sstevel@tonic-gate }
8290Sstevel@tonic-gate 
8300Sstevel@tonic-gate static int intrupt;
8310Sstevel@tonic-gate 
8329694SScott.Rotondo@Sun.COM static void catch();
8339694SScott.Rotondo@Sun.COM 
8340Sstevel@tonic-gate unsigned char *
mypass(prompt)8350Sstevel@tonic-gate mypass(prompt)
8360Sstevel@tonic-gate unsigned char	*prompt;
8370Sstevel@tonic-gate {
8380Sstevel@tonic-gate 	struct termio ttyb;
8390Sstevel@tonic-gate 	unsigned short flags;
840802Scf46844 	unsigned char *p;
841802Scf46844 	int c;
8420Sstevel@tonic-gate 	static unsigned char pbuf[9];
8430Sstevel@tonic-gate 	void	(*sig)();
8440Sstevel@tonic-gate 
8450Sstevel@tonic-gate 	setbuf(stdin, (char*)NULL);
8460Sstevel@tonic-gate 	sig = signal(SIGINT, catch);
8470Sstevel@tonic-gate 	intrupt = 0;
8480Sstevel@tonic-gate 	(void) ioctl(fileno(stdin), TCGETA, &ttyb);
8490Sstevel@tonic-gate 	flags = ttyb.c_lflag;
8500Sstevel@tonic-gate 	ttyb.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
8510Sstevel@tonic-gate 	(void) ioctl(fileno(stdin), TCSETAF, &ttyb);
8520Sstevel@tonic-gate 	(void) fputs((char *)prompt, stderr);
8530Sstevel@tonic-gate 	for(p=pbuf; !intrupt && (c = getc(stdin)) != '\n' && c!= '\r' && c != EOF; ) {
8540Sstevel@tonic-gate 		if(p < &pbuf[8])
8550Sstevel@tonic-gate 			*p++ = c;
8560Sstevel@tonic-gate 	}
8570Sstevel@tonic-gate 	*p = '\0';
8580Sstevel@tonic-gate 	(void) putc('\n', stderr);
8590Sstevel@tonic-gate 	ttyb.c_lflag = flags;
8600Sstevel@tonic-gate 	(void) ioctl(fileno(stdin), TCSETA, &ttyb);
8610Sstevel@tonic-gate 	(void) signal(SIGINT, sig);
8620Sstevel@tonic-gate 	if(intrupt)
8630Sstevel@tonic-gate 		(void) kill(getpid(), SIGINT);
8640Sstevel@tonic-gate 	return(pbuf);
8650Sstevel@tonic-gate }
8660Sstevel@tonic-gate 
8670Sstevel@tonic-gate static void
catch()8680Sstevel@tonic-gate catch()
8690Sstevel@tonic-gate {
8700Sstevel@tonic-gate 	++intrupt;
8710Sstevel@tonic-gate }
872