/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/* Copyright (c) 1981 Regents of the University of California */
#include <stdio.h> /* BUFSIZ: stdio = 1024, VMUNIX = 1024 */
#ifndef TRACE
#endif
#include "ex.h"
#include "ex_temp.h"
#include "ex_tty.h"
#include "ex_tune.h"
#include <pwd.h>
#include <locale.h>
#include <dirent.h>
#include <unistd.h>
#include <errno.h>
/*
*
* This program searches through the specified directory and then
* the directory usrpath(preserve) looking for an instance of the specified
* file from a crashed editor or a crashed system.
* If this file is found, it is unscrambled and written to
* the standard output.
*
* If this program terminates without a "broken pipe" diagnostic
* (i.e. the editor doesn't die right away) then the buffer we are
* writing from is removed when we finish. This is potentially a mistake
* as there is not enough handshaking to guarantee that the file has actually
* been recovered, but should suffice for most cases.
*/
/*
* This directory definition also appears (obviously) in expreserve.c.
* Change both if you change either.
*/
/*
* Limit on the number of printed entries
* when an, e.g. ``ex -r'' command is given.
*/
void rputfile(void);
void rsyserror(void);
void searchdir(unsigned char *);
void scrapbad(void);
void findtmp(unsigned char *);
void listfiles(unsigned char *);
int
{
unsigned char *cp;
int c, b, i;
int label;
extern unsigned char *mypass();
#if !defined(TEXT_DOMAIN)
#endif
(void)textdomain(TEXT_DOMAIN);
exit(-1);
}
/*
* Initialize as though the editor had just started.
*/
switch (c) {
case 'r':
rflg++;
break;
case 'x':
xflag++;
break;
case '?':
errflg++;
break;
}
if (errflg)
exit(2);
/*
* If given only a -r argument, then list the saved files.
* (NOTE: single -r argument is scheduled to be replaced by -L).
*/
exit(0);
}
if (argc != 2)
/*
* Search for this file.
*/
/*
* Got (one of the versions of) it, write it back to the editor.
*/
gettext(" [Dated: %s, newest of %d saved]") :
if(H.encrypted) {
if(xflag) {
} else
if(kflag == -1) {
kflag = 0;
xflag = 0;
exit(-1);
}
xtflag = 1;
xtflag = 0;
exit(-1);
}
}
H.Flines++;
/*
* Allocate space for the line pointers from the temp file.
*/
#ifdef DEBUG
#endif
/*
* Now go get the blocks of seek pointers which are scattered
* throughout the temp file, reconstructing the incore
* line pointers at point of crash.
*/
b = 0;
while (H.Flines > 0) {
exit(1);
}
b++;
}
/*
* Due to sandbagging some lines may really not be there.
* Find and discard such. This shouldn't happen often.
*/
scrapbad();
/*
* Now if there were any lines in the recovered file
* write them to the standard output.
*/
rputfile();
}
/*
* Trash the saved buffer.
* Hopefully the system won't crash before the editor
* syncs the new recovered buffer; i.e. for an instant here
* you may lose if the system crashes because this file
* is gone, but the editor hasn't completed reading the recovered
* file from the pipe from us to it.
*
* This doesn't work if we are coming from an non-absolute path
* name since we may have chdir'ed but what the hay, noone really
* ever edits with temporaries in "." anyways.
*/
if (nb[0] == '/') {
}
return (0);
}
/*
* Print an error message (notably not in error
* message file). If terminal is in RAW mode, then
* we should be writing output for "vi", so don't print
* a newline which would mess up the screen.
*/
/*VARARGS2*/
void
unsigned char *str;
int inf;
{
if (inf)
else
exit(1);
}
/*
* Here we save the information about files, when
* you ask us what files we have saved for you.
* We buffer file name, number of lines, and the time
* at which the file was saved.
*/
struct svfile {
int sf_lines;
short sf_encrypted;
};
void
{
int f;
unsigned char *filname;
/*
* Open usrpath(preserve), and go there to make things quick.
*/
{
return;
}
return;
}
/*
* Look at the candidate files in usrpath(preserve).
*/
ecount = 0;
{
if (filname[0] != 'E')
continue;
#ifdef DEBUG
#endif
/*
* Name begins with E; open it and
* make sure the uid in the header is our uid.
* If not, then don't bother with this file, it can't
* be ours.
*/
if (f < 0) {
#ifdef DEBUG
#endif
continue;
}
if (read(f, (char *) &H, sizeof H) != sizeof H) {
#ifdef DEBUG
#endif
(void)close(f);
continue;
}
(void)close(f);
#ifdef DEBUG
#endif
continue;
}
/*
* Saved the day!
*/
ecount++;
#ifdef DEBUG
#endif
}
/*
* If any files were saved, then sort them and print
* them out.
*/
if (ecount == 0) {
return;
}
gettext("On %s at %s, saved %d lines of file \"%s\" "),
}
}
/*
* Enter a new file into the saved file information.
*/
void
{
f = 0;
/*
* Trash the oldest as the most useless.
*/
break;
fp = f;
}
/*
* Gotcha.
*/
*cp2++ = 0;
*cp2++ = 0;
}
/*
* Do the qsort compare to sort the entries first by file name,
* then by modify time.
*/
int
{
int t;
return(t);
return(-1);
}
/*
* Scratch for search.
*/
/*
* Look for a file, both in the users directory option value
* (i.e. usually /tmp) and in usrpath(preserve).
* Want to find the newest so we search on and on.
*/
void
{
/*
* No name or file so far.
*/
bestnb[0] = 0;
bestfd = -1;
/*
* Search usrpath(preserve) and, if we can get there, /tmp
* (actually the user's "directory" option).
*/
if (bestfd != -1) {
/*
* Gotcha.
* Put the file (which is already open) in the file
* used by the temp file routines, and save its
* name for later unlinking.
*/
/*
* Gotta be able to read the header or fall through
* to lossage.
*/
return;
}
/*
* Extreme lossage...
*/
}
/*
* Search for the file in directory dirname.
*
* Don't chdir here, because the users directory
* may be ".", and we would move away before we searched it.
* Note that we actually chdir elsewhere (because it is too slow
* to look around in usrpath(preserve) without chdir'ing there) so we
* can't win, because we don't know the name of '.' and if the path
* name of the file we want to unlink is relative, rather than absolute
* we won't be able to find it again.
*/
void
{
unsigned char *filname;
return;
{
continue;
/*
* Got a file in the directory starting with Ex...
* Save a consed up name for the file to unlink
* later, and check that this is really a file
* we are looking for.
*/
/*
* Well, it is the file we are looking for.
* Is it more recent than any version we found before?
*/
/*
* A winner.
*/
}
/*
* Count versions and tell user
*/
vercnt++;
}
}
}
/*
* Given a candidate file to be recovered, see
* if it's really an editor temporary and of this
* user and the file specified.
*/
int
{
if (tfile < 0)
return (0);
nope:
return (0);
}
goto nope;
goto nope;
/*
* Old code: puts a word LOST in the header block, so that lost lines
* can be made to point at it.
*/
return (1);
}
/*
* Find the true end of the scratch file, and ``LOSE''
* lines which point into thin air. This lossage occurs
* due to the sandbagging of i/o which can cause blocks to
* be written in a non-obvious order, different from the order
* in which the editor tried to write them.
*
* Lines which are lost are replaced with the text LOST so
* they are easy to find. We work hard at pretty formatting here
* as lines tend to be lost in blocks.
*
* This only seems to happen on very heavily loaded systems, and
* not very often.
*/
void
scrapbad(void)
{
#ifdef DEBUG
#endif
/*
* Look for a null separating two lines in the temp file;
* if last line was split across blocks, then it is lost
* if the last block is.
*/
while (bno > 0) {
if(xtflag)
rsyserror();
#ifdef DEBUG
#endif
while (cnt > 0)
goto null;
bno--;
}
null:
/*
* Magically calculate the largest valid pointer in the temp file,
* consing it up from the block number and the count.
*/
#ifdef DEBUG
#endif
/*
* Now cycle through the line pointers,
* trashing the Lusers.
*/
#ifdef DEBUG
#endif
if (was == 0)
} else if (was) {
if (bad == 0)
bad++;
was = 0;
}
if (was != 0) {
if (bad == 0)
bad++;
}
if (bad)
}
/*
* Following routines stolen mercilessly from ex.
*/
void
rputfile(void)
{
int nib;
clrstats();
if (cntln == 0)
return;
do {
#ifdef DEBUG
#endif
#ifdef DEBUG
#endif
for (;;) {
if (--nib < 0) {
wrerror();
}
break;
}
}
wrerror();
}
void
wrerror(void)
{
rsyserror();
}
void
clrstats(void)
{
ninbuf = 0;
cntch = 0;
cntln = 0;
cntnull = 0;
cntodd = 0;
}
#define READ 0
void
{
int nl;
if (--nl == 0) {
}
}
int read();
int write();
unsigned char *
{
int n;
#ifdef DEBUG
#endif
if(xtflag)
rsyserror();
#ifdef DEBUG
#endif
}
void
{
int rc;
perror("");
rsyserror();
}
}
void
rsyserror(void)
{
dirtcnt = 0;
exit(1);
}
static int intrupt;
static void catch();
unsigned char *
unsigned char *prompt;
{
unsigned short flags;
unsigned char *p;
int c;
void (*sig)();
intrupt = 0;
if(p < &pbuf[8])
*p++ = c;
}
*p = '\0';
if(intrupt)
return(pbuf);
}
static void
catch()
{
++intrupt;
}