* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
static char copyright
[] =
"@(#) Copyright (c) 1991, 1993\n\
The Regents of the University of California. All rights reserved.\n";
static char sccsid
[] = "@(#)ex3.7preserve.c 8.1 (Berkeley) 6/9/93";
* Expreserve - preserve a file in _PATH_PRESERVE.
* Bill Joy UCB November 13, 1977
* This routine is very naive - it doesn't remove anything from
* _PATH_PRESERVE... this may mean that we leave stuff there...
* the danger in doing anything with _PATH_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 arguments
* and the standard input open on the temp file. Second with an
* argument to preserve the entire contents of _PATH_VARTMP (root only).
* BUG: should do something about preserving Rx... (register contents)
time_t Time
; /* Time temp file last updated */
int 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 */
while ((ch
= getopt(argc
, argv
, "a")) != EOF
)
if (chdir(_PATH_PRESERVE
) < 0)
* If only one argument, then preserve the standard input.
exit(copyout(NULL
) ? 1 : 0);
* If not super user, then can only preserve standard input.
* ... else preserve all the stuff in /var/tmp, removing
if (!(tf
= opendir(_PATH_VARTMP
)))
while ((dirent
= readdir(tf
)) != NULL
) {
/* Ex temporaries must begin with Ex. */
if (dirent
->d_name
[0] != 'E' || dirent
->d_name
[1] != 'x')
(void)sprintf(path
, "%s/%s", _PATH_VARTMP
, dirent
->d_name
);
if (stat(path
, &stbuf
) || !S_ISREG(stbuf
.st_mode
))
register int ifd
, ofd
, nr
, nw
, off
, rval
;
char buf
[8*1024], fname
[20];
/* Open any given file name. */
if ((ifd
= open(name
, O_RDWR
)) < 0)
/* vi hands us an fd, it's not necessarily at the beginning. */
(void)lseek(ifd
, 0l, SEEK_SET
);
if (read(ifd
, &H
, sizeof(H
)) != sizeof(H
))
* Consistency checks so we don't copy out garbage.
"ex3.7preserve: negative number of lines\n");
if (H
.Blocks
[0] != HBLKS
|| H
.Blocks
[1] != HBLKS
+1) {
"ex3.7preserve: blocks %d %d\n", H
.Blocks
[0], H
.Blocks
[1]);
if (!name
&& H
.Uid
!= getuid()) {
(void)fprintf(stderr
, "ex3.7preserve: wrong user-id\n");
if (lseek(ifd
, 0l, SEEK_SET
)) {
"ex3.7preserve: negative number of lines\n");
format
: (void)fprintf(stderr
, "ex3.7preserve: %s\n", strerror(EFTYPE
));
* If no name was assigned to the file, then give it the name
* LOST, by putting this in the header. This involves overwriting
if (H
.Savedfile
[0] == 0) {
(void)strcpy(H
.Savedfile
, "LOST");
(void)write(ifd
, &H
, sizeof(H
));
(void)lseek(ifd
, 0l, SEEK_SET
);
/* File is good. Get a name and create a file for the copy. */
(void)strcpy(fname
, "ExXXXXXX");
if ((ofd
= mkstemp(fname
)) == -1)
while ((nr
= read(ifd
, buf
, sizeof(buf
))) > 0)
for (off
= 0; off
< nr
; nr
-= nw
, off
+= nw
)
if ((nw
= write(ofd
, buf
+ off
, nr
)) < 0) {
"ex3.7preserve: tmp file: %s\n",
(void)fprintf(stderr
, "ex3.7preserve: %s: %s\n",
name
? name
: "stdin", strerror(errno
));
(void)fchown(ofd
, H
.Uid
, 0);
notify(H
.Uid
, H
.Savedfile
, (int)name
, H
.Time
);
/* Notify user uid that his file fname has been saved. */
notify(uid
, fname
, flag
, time
)
static char hostname
[MAXHOSTNAMELEN
], *timestamp
;
char cmd
[MAXPATHLEN
+ 50], croak
[50];
(void)gethostname(hostname
, sizeof(hostname
));
timestamp
= ctime(&time
);
timestamp
[16] = 0; /* blast from seconds on */
(void)snprintf(cmd
, sizeof(cmd
),
"%s -i -t -F \"The Editor\" -f root", _PATH_SENDMAIL
);
"Reply-To: root@%s\nFrom: root@%s (The Editor)\nTo: %s\n",
hostname
, hostname
, pp
->pw_name
);
* flag says how the editor croaked: "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
(void)snprintf(croak
, sizeof(croak
),
flag
? "the system went down"
: "the editor was killed");
if (!fname
|| !fname
[0]) {
fprintf(mf
, "Subject: editor saved \"LOST\"\n\n");
fprintf(mf
, "You were editing a file without a name\n");
fprintf(mf
, "at %s on the machine %s when %s.\n",
timestamp
, hostname
, croak
);
"Since the file had no name, it has been named \"LOST\".\n");
fprintf(mf
, "Subject: editor saved \"%s\"\n\n", fname
);
fprintf(mf
, "You were editing the file %s\n", fname
);
fprintf(mf
, "at %s on the machine %s\n", timestamp
, hostname
);
fprintf(mf
, "when %s.\n", croak
);
fprintf(mf
, "\nYou can retrieve most of your changes to this file\n");
fprintf(mf
, "using the \"recover\" command of the editor.\n");
"An easy way to do this is to give the command \"vi -r %s\".\n",
fprintf(mf
, "This method also works using \"ex\" and \"edit\".\n\n");
(void)fprintf(stderr
, "ex3.7preserve: ");
(void)fprintf(stderr
, "%s: ", msg
);
(void)fprintf(stderr
, "%s\n", strerror(errno
));
(void)fprintf(stderr
, "usage: ex3.7preserve [-a]\n");