/* Copyright (c) 1980 Regents of the University of California */
static char *sccsid
= "@(#)expreserve.c 6.1 10/18/80";
* Expreserve - preserve a file in usrpath(preserve)
* Bill Joy UCB November 13, 1977
* This routine is very naive - it doesn't remove anything from
* usrpath(preserve)... this may mean that we will be unable to preserve
* stuff there... the danger in doing anything with usrpath(preserve)
* is that the clock may be screwed up and we may get confused.
* We are called in two ways - first from the editor with no argumentss
* and the standard input open on the temp file. Second with an argument
* to preserve the entire contents of /tmp (root only).
* BUG: should do something about preserving Rx... (register contents)
time_t Time
; /* Time temp file last updated */
short Uid
; /* This users identity */
short Flines
; /* Number of lines in file */
char Savedfile
[FNSIZE
]; /* The current file name */
short Blocks
[LBLKS
]; /* Blocks where line pointers stashed */
#define ignore(a) Ignore(a)
#define ignorl(a) Ignorl(a)
struct passwd
*getpwuid();
#define eq(a, b) strcmp(a, b) == 0
* If only one argument, then preserve the standard input.
* If not super user, then can only preserve standard input.
fprintf(stderr
, "NOT super user\n");
* ... else preserve all the stuff in /tmp, removing
while (fread((char *) &dirent
, sizeof dirent
, 1, tf
) == 1) {
* Ex temporaries must begin with Ex;
* we check that the 10th character of the name is null
* so we won't have to worry about non-null terminated names
if (dirent
.d_name
[0] != 'E' || dirent
.d_name
[1] != 'x' || dirent
.d_name
[10])
if (stat(dirent
.d_name
, &stbuf
))
if ((stbuf
.st_mode
& S_IFMT
) != S_IFREG
)
ignore(copyout(dirent
.d_name
));
char pattern
[] = usrpath(preserve
/Exaa`XXXXX
);
* Copy file name into usrpath(preserve)/...
* If name is (char *) 0, then do the standard input.
* We make some checks on the input to make sure it is
* really an editor temporary, generate a name for the
* file (this is the slowest thing since we must stat
* to find a unique name), and finally copy the file.
* The first time we put in the digits of our
* process number at the end of the pattern.
* If a file name was given, make it the standard
* Need read/write access for arcane reasons
if (read(0, (char *) &H
, sizeof H
) != sizeof H
) {
fprintf(stderr
, "Buffer format error\t");
* Consistency checsks so we don't copy out garbage.
fprintf(stderr
, "Negative number of lines\n");
if (H
.Blocks
[0] != HBLKS
|| H
.Blocks
[1] != HBLKS
+1) {
fprintf(stderr
, "Blocks %d %d\n", H
.Blocks
[0], H
.Blocks
[1]);
if (name
== 0 && H
.Uid
!= getuid()) {
fprintf(stderr
, "Wrong user-id\n");
fprintf(stderr
, "Negative number of lines\n");
* If no name was assigned to the file, then give it the name
* LOST, by putting this in the header.
if (H
.Savedfile
[0] == 0) {
strcpy(H
.Savedfile
, "LOST");
ignore(write(0, (char *) &H
, sizeof H
));
* File is good. Get a name and create a file for the copy.
if (creat(pattern
, 0600) < 0) {
* Make the target be owned by the owner of the file.
ignore(chown(pattern
, H
.Uid
, 0));
i
= read(0, buf
, BUFSIZ
);
perror("Buffer read error");
notify(H
.Uid
, H
.Savedfile
, (int) name
);
if (write(1, buf
, i
) != i
) {
* Blast the last 5 characters of cp to be the process number.
for (i
= getpid(), j
= 5, cp
+= strlen(cp
); j
> 0; i
/= 10, j
--)
* Make the name in cp be unique by clobbering up to
* three alphabetic characters into a sequence of the form 'aab', 'aac', etc.
* Mktemp gets weird names too quickly to be useful here.
dcp
= cp
+ strlen(cp
) - 1;
fprintf(stderr
, "Can't find a name\t");
* Notify user uid that his file fname has been saved.
struct passwd
*pp
= getpwuid(uid
);
sprintf(cmd
, "mail %s", pp
->pw_name
);
"A copy of an editor buffer of yours was saved when %s.\n",
flag
? "the system went down" : "the editor was killed");
"No name was associated with this buffer so it has been named \"LOST\".\n");
"A copy of an editor buffer of your file \"%s\"\nwas saved when %s.\n", fname
,
* "the editor was killed" is perhaps still not an ideal
* error message. Usually, either it was forcably terminated
* or the phone was hung up, but we don't know which.
flag
? "the system went down" : "the editor was killed");
"This buffer can be retrieved using the \"recover\" command of the editor.\n");
"An easy way to do this is to give the command \"ex -r %s\".\n",fname
);
"This works for \"edit\" and \"vi\" also.\n");