[9] | 1 | /* elvprsv.c */
|
---|
| 2 |
|
---|
| 3 | /* Author:
|
---|
| 4 | * Steve Kirkendall
|
---|
| 5 | * 14407 SW Teal Blvd. #C
|
---|
| 6 | * Beaverton, OR 97005
|
---|
| 7 | * kirkenda@cs.pdx.edu
|
---|
| 8 | */
|
---|
| 9 |
|
---|
| 10 |
|
---|
| 11 | /* This file contains the portable sources for the "elvprsv" program.
|
---|
| 12 | * "Elvprsv" is run by Elvis when Elvis is about to die. It is also
|
---|
| 13 | * run when the computer boots up. It is not intended to be run directly
|
---|
| 14 | * by the user, ever.
|
---|
| 15 | *
|
---|
| 16 | * Basically, this program does the following four things:
|
---|
| 17 | * - It extracts the text from the temporary file, and places the text in
|
---|
| 18 | * a file in the /usr/preserve directory.
|
---|
| 19 | * - It adds a line to the /usr/preserve/Index file, describing the file
|
---|
| 20 | * that it just preserved.
|
---|
| 21 | * - It removes the temporary file.
|
---|
| 22 | * - It sends mail to the owner of the file, saying that the file was
|
---|
| 23 | * preserved, and how it can be recovered.
|
---|
| 24 | *
|
---|
| 25 | * The /usr/preserve/Index file is a log file that contains one line for each
|
---|
| 26 | * file that has ever been preserved. Each line of this file describes one
|
---|
| 27 | * preserved file. The first word on the line is the name of the file that
|
---|
| 28 | * contains the preserved text. The second word is the full pathname of the
|
---|
| 29 | * file that was being edited; for anonymous buffers, this is the directory
|
---|
| 30 | * name plus "/foo".
|
---|
| 31 | *
|
---|
| 32 | * If elvprsv's first argument (after the command name) starts with a hyphen,
|
---|
| 33 | * then the characters after the hyphen are used as a description of when
|
---|
| 34 | * the editor went away. This is optional.
|
---|
| 35 | *
|
---|
| 36 | * The remaining arguments are all the names of temporary files that are
|
---|
| 37 | * to be preserved. For example, on a UNIX system, the /etc/rc file might
|
---|
| 38 | * invoke it this way:
|
---|
| 39 | *
|
---|
| 40 | * elvprsv "-the system went down" /tmp/elv_*.*
|
---|
| 41 | *
|
---|
| 42 | * This file contains only the portable parts of the preserve program.
|
---|
| 43 | * It must #include a system-specific file. The system-specific file is
|
---|
| 44 | * expected to define the following functions:
|
---|
| 45 | *
|
---|
| 46 | * char *ownername(char *filename) - returns name of person who owns file
|
---|
| 47 | *
|
---|
| 48 | * void mail(char *user, char *name, char *when)
|
---|
| 49 | * - tell user that file was preserved
|
---|
| 50 | */
|
---|
| 51 |
|
---|
| 52 | #include <stdio.h>
|
---|
| 53 | #include "config.h"
|
---|
| 54 | #include "vi.h"
|
---|
| 55 |
|
---|
| 56 | #if AMIGA
|
---|
| 57 | BLK tmpblk;
|
---|
| 58 | #error AMIGA here DEBUG
|
---|
| 59 | # include "amiwild.c"
|
---|
| 60 | # include "amiprsv.c"
|
---|
| 61 | #endif
|
---|
| 62 |
|
---|
| 63 | #if OSK
|
---|
| 64 | # undef sprintf
|
---|
| 65 | #endif
|
---|
| 66 |
|
---|
| 67 | #if ANY_UNIX || OSK
|
---|
| 68 | # include "prsvunix.c"
|
---|
| 69 | #endif
|
---|
| 70 |
|
---|
| 71 | #if MSDOS || TOS
|
---|
| 72 | # include "prsvdos.c"
|
---|
| 73 | # define WILDCARD_NO_MAIN
|
---|
| 74 | # include "wildcard.c"
|
---|
| 75 | #endif
|
---|
| 76 |
|
---|
| 77 |
|
---|
| 78 | BLK buf;
|
---|
| 79 | BLK hdr;
|
---|
| 80 | BLK name;
|
---|
| 81 | int rewrite_now; /* boolean: should we send text directly to orig file? */
|
---|
| 82 |
|
---|
| 83 |
|
---|
| 84 |
|
---|
| 85 | /* This function preserves a single file, and announces its success/failure
|
---|
| 86 | * via an e-mail message.
|
---|
| 87 | */
|
---|
| 88 | void preserve(tname, when)
|
---|
| 89 | char *tname; /* name of a temp file to be preserved */
|
---|
| 90 | char *when; /* description of when the editor died */
|
---|
| 91 | {
|
---|
| 92 | int infd; /* fd used for reading from the temp file */
|
---|
| 93 | FILE *outfp; /* fp used for writing to the recovery file */
|
---|
| 94 | FILE *index; /* fp used for appending to index file */
|
---|
| 95 | char outname[100]; /* the name of the recovery file */
|
---|
| 96 | char *user; /* name of the owner of the temp file */
|
---|
| 97 | #if AMIGA
|
---|
| 98 | char *prsvdir;
|
---|
| 99 | #endif
|
---|
| 100 | int i;
|
---|
| 101 |
|
---|
| 102 | /* open the temp file */
|
---|
| 103 | infd = open(tname, O_RDONLY|O_BINARY);
|
---|
| 104 | if (infd < 0)
|
---|
| 105 | {
|
---|
| 106 | /* if we can't open the file, then we should assume that
|
---|
| 107 | * the filename contains wildcard characters that weren't
|
---|
| 108 | * expanded... and also assume that they weren't expanded
|
---|
| 109 | * because there are no files that need to be preserved.
|
---|
| 110 | * THEREFORE... we should silently ignore it.
|
---|
| 111 | * (Or loudly ignore it if the user was using -R)
|
---|
| 112 | */
|
---|
| 113 | if (rewrite_now)
|
---|
| 114 | {
|
---|
| 115 | perror(tname);
|
---|
| 116 | }
|
---|
| 117 | return;
|
---|
| 118 | }
|
---|
| 119 |
|
---|
| 120 | /* read the header and name from the file */
|
---|
| 121 | if (read(infd, hdr.c, BLKSIZE) != BLKSIZE
|
---|
| 122 | || read(infd, name.c, BLKSIZE) != BLKSIZE)
|
---|
| 123 | {
|
---|
| 124 | /* something wrong with the file - sorry */
|
---|
| 125 | fprintf(stderr, "%s: trucated header blocks\n", tname);
|
---|
| 126 | close(infd);
|
---|
| 127 | return;
|
---|
| 128 | }
|
---|
| 129 |
|
---|
| 130 | /* If the filename block contains an empty string, then Elvis was
|
---|
| 131 | * only keeping the temp file around because it contained some text
|
---|
| 132 | * that was needed for a named cut buffer. The user doesn't care
|
---|
| 133 | * about that kind of temp file, so we should silently delete it.
|
---|
| 134 | */
|
---|
| 135 | if (name.c[0] == '\0' && name.c[1] == '\177')
|
---|
| 136 | {
|
---|
| 137 | close(infd);
|
---|
| 138 | unlink(tname);
|
---|
| 139 | return;
|
---|
| 140 | }
|
---|
| 141 |
|
---|
| 142 | if (rewrite_now)
|
---|
| 143 | {
|
---|
| 144 | /* we don't need to open the index file */
|
---|
| 145 | index = (FILE *)0;
|
---|
| 146 |
|
---|
| 147 | /* make sure we can read every block! */
|
---|
| 148 | for (i = 1; i < MAXBLKS && hdr.n[i]; i++)
|
---|
| 149 | {
|
---|
| 150 | lseek(infd, (long)hdr.n[i] * (long)BLKSIZE, 0);
|
---|
| 151 | if (read(infd, buf.c, BLKSIZE) != BLKSIZE)
|
---|
| 152 | {
|
---|
| 153 | /* messed up header */
|
---|
| 154 | fprintf(stderr, "%s: unrecoverable -- header trashed\n", name.c);
|
---|
| 155 | close(infd);
|
---|
| 156 | return;
|
---|
| 157 | }
|
---|
| 158 | }
|
---|
| 159 |
|
---|
| 160 | /* open the user's file for writing */
|
---|
| 161 | outfp = fopen(name.c, "w");
|
---|
| 162 | if (!outfp)
|
---|
| 163 | {
|
---|
| 164 | perror(name.c);
|
---|
| 165 | close(infd);
|
---|
| 166 | return;
|
---|
| 167 | }
|
---|
| 168 | }
|
---|
| 169 | else
|
---|
| 170 | {
|
---|
| 171 | /* open/create the index file */
|
---|
| 172 | index = fopen(PRSVINDEX, "a");
|
---|
| 173 | if (!index)
|
---|
| 174 | {
|
---|
| 175 | perror(PRSVINDEX);
|
---|
| 176 | exit(1);
|
---|
| 177 | }
|
---|
| 178 |
|
---|
| 179 | /* create the recovery file in the PRESVDIR directory */
|
---|
| 180 | #if AMIGA
|
---|
| 181 | prsvdir = &PRSVDIR[strlen(PRSVDIR) - 1];
|
---|
| 182 | if (*prsvdir == '/' || *prsvdir == ':')
|
---|
| 183 | {
|
---|
| 184 | sprintf(outname, "%sp%ld", PRSVDIR, ftell(index));
|
---|
| 185 | }
|
---|
| 186 | else
|
---|
| 187 | #endif
|
---|
| 188 | sprintf(outname, "%s%cp%ld", PRSVDIR, SLASH, ftell(index));
|
---|
| 189 | outfp = fopen(outname, "w");
|
---|
| 190 | if (!outfp)
|
---|
| 191 | {
|
---|
| 192 | perror(outname);
|
---|
| 193 | close(infd);
|
---|
| 194 | fclose(index);
|
---|
| 195 | return;
|
---|
| 196 | }
|
---|
| 197 | }
|
---|
| 198 |
|
---|
| 199 | /* write the text of the file out to the recovery file */
|
---|
| 200 | for (i = 1; i < MAXBLKS && hdr.n[i]; i++)
|
---|
| 201 | {
|
---|
| 202 | lseek(infd, (long)hdr.n[i] * (long)BLKSIZE, 0);
|
---|
| 203 | if (read(infd, buf.c, BLKSIZE) != BLKSIZE)
|
---|
| 204 | {
|
---|
| 205 | /* messed up header */
|
---|
| 206 | fprintf(stderr, "%s: unrecoverable -- header trashed\n", name.c);
|
---|
| 207 | fclose(outfp);
|
---|
| 208 | close(infd);
|
---|
| 209 | if (index)
|
---|
| 210 | {
|
---|
| 211 | fclose(index);
|
---|
| 212 | }
|
---|
| 213 | unlink(outname);
|
---|
| 214 | return;
|
---|
| 215 | }
|
---|
| 216 | fputs(buf.c, outfp);
|
---|
| 217 | }
|
---|
| 218 |
|
---|
| 219 | /* add a line to the index file */
|
---|
| 220 | if (index)
|
---|
| 221 | {
|
---|
| 222 | fprintf(index, "%s %s\n", outname, name.c);
|
---|
| 223 | }
|
---|
| 224 |
|
---|
| 225 | /* close everything */
|
---|
| 226 | close(infd);
|
---|
| 227 | fclose(outfp);
|
---|
| 228 | if (index)
|
---|
| 229 | {
|
---|
| 230 | fclose(index);
|
---|
| 231 | }
|
---|
| 232 |
|
---|
| 233 | /* Are we doing this due to something more frightening than just
|
---|
| 234 | * a ":preserve" command?
|
---|
| 235 | */
|
---|
| 236 | if (*when)
|
---|
| 237 | {
|
---|
| 238 | /* send a mail message */
|
---|
| 239 | mail(ownername(tname), name.c, when);
|
---|
| 240 |
|
---|
| 241 | /* remove the temp file -- the editor has died already */
|
---|
| 242 | unlink(tname);
|
---|
| 243 | }
|
---|
| 244 | }
|
---|
| 245 |
|
---|
| 246 | main(argc, argv)
|
---|
| 247 | int argc;
|
---|
| 248 | char **argv;
|
---|
| 249 | {
|
---|
| 250 | int i;
|
---|
| 251 | char *when = "the editor went away";
|
---|
| 252 |
|
---|
| 253 | #if MSDOS || TOS
|
---|
| 254 | /* expand any wildcards in the command line */
|
---|
| 255 | argv = wildexpand(&argc, argv);
|
---|
| 256 | #endif
|
---|
| 257 |
|
---|
| 258 | /* do we have a "when" argument? */
|
---|
| 259 | i = 1;
|
---|
| 260 | if (argc >= i + 1 && !strcmp(argv[i], "-R"))
|
---|
| 261 | {
|
---|
| 262 | rewrite_now = 1;
|
---|
| 263 | when = "";
|
---|
| 264 | i++;
|
---|
| 265 | #if ANY_UNIX
|
---|
| 266 | setuid(geteuid());
|
---|
| 267 | #endif
|
---|
| 268 | }
|
---|
| 269 | #if OSK
|
---|
| 270 | else
|
---|
| 271 | {
|
---|
| 272 | setuid(0);
|
---|
| 273 | }
|
---|
| 274 | #endif
|
---|
| 275 | if (argc >= i + 1 && argv[i][0] == '-')
|
---|
| 276 | {
|
---|
| 277 | when = argv[i] + 1;
|
---|
| 278 | i++;
|
---|
| 279 | }
|
---|
| 280 |
|
---|
| 281 | /* preserve everything we're supposed to */
|
---|
| 282 | while (i < argc)
|
---|
| 283 | {
|
---|
| 284 | preserve(argv[i], when);
|
---|
| 285 | i++;
|
---|
| 286 | }
|
---|
| 287 | }
|
---|