|
|
1.1 root 1: /* elvprsv.c */
2:
3: /* Author:
4: * Steve Kirkendall
5: * 14407 SW Teal Blvd. #C
6: * Beaverton, OR 97005
7: * [email protected]
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: #include "ctype.h"
56:
57: void preserve P_((char *, char *));
58: void main P_((int, char **));
59:
60: #if AMIGA
61: BLK tmpblk;
62: # include "amiwild.c"
63: # include "amiprsv.c"
64: #endif
65:
66: #if OSK
67: # undef sprintf
68: #endif
69:
70: #if ANY_UNIX || OSK
71: # include "prsvunix.c"
72: #endif
73:
74: #if MSDOS || TOS
75: # include "prsvdos.c"
76: # define WILDCARD_NO_MAIN
77: # include "wildcard.c"
78: #endif
79:
80:
81: BLK buf;
82: BLK hdr;
83: BLK name;
84: int rewrite_now; /* boolean: should we send text directly to orig file? */
85:
86:
87:
88: /* This function preserves a single file, and announces its success/failure
89: * via an e-mail message.
90: */
91: void preserve(tname, when)
92: char *tname; /* name of a temp file to be preserved */
93: char *when; /* description of when the editor died */
94: {
95: int infd; /* fd used for reading from the temp file */
96: FILE *outfp; /* fp used for writing to the recovery file */
97: FILE *index; /* fp used for appending to index file */
98: char outname[100]; /* the name of the recovery file */
99: char *user; /* name of the owner of the temp file */
100: #if AMIGA
101: char *prsvdir;
102: #endif
103: int i;
104:
105: /* open the temp file */
106: infd = open(tname, O_RDONLY|O_BINARY);
107: if (infd < 0)
108: {
109: /* if we can't open the file, then we should assume that
110: * the filename contains wildcard characters that weren't
111: * expanded... and also assume that they weren't expanded
112: * because there are no files that need to be preserved.
113: * THEREFORE... we should silently ignore it.
114: * (Or loudly ignore it if the user was using -R)
115: */
116: if (rewrite_now)
117: {
118: perror(tname);
119: }
120: return;
121: }
122:
123: /* read the header and name from the file */
124: if (read(infd, hdr.c, BLKSIZE) != BLKSIZE
125: || read(infd, name.c, BLKSIZE) != BLKSIZE)
126: {
127: /* something wrong with the file - sorry */
128: fprintf(stderr, "%s: truncated header blocks\n", tname);
129: close(infd);
130: return;
131: }
132:
133: /* If the filename block contains an empty string, then Elvis was
134: * only keeping the temp file around because it contained some text
135: * that was needed for a named cut buffer. The user doesn't care
136: * about that kind of temp file, so we should silently delete it.
137: */
138: if (name.c[0] == '\0' && name.c[1] == '\177')
139: {
140: close(infd);
141: unlink(tname);
142: return;
143: }
144:
145: if (rewrite_now)
146: {
147: /* we don't need to open the index file */
148: index = (FILE *)0;
149:
150: /* make sure we can read every block! */
151: for (i = 1; i < MAXBLKS && hdr.n[i]; i++)
152: {
153: lseek(infd, (long)hdr.n[i] * (long)BLKSIZE, 0);
154: if (read(infd, buf.c, BLKSIZE) != BLKSIZE)
155: {
156: /* messed up header */
157: fprintf(stderr, "%s: unrecoverable -- header trashed\n", name.c);
158: close(infd);
159: return;
160: }
161: }
162:
163: /* open the user's file for writing */
164: outfp = fopen(name.c, "w");
165: if (!outfp)
166: {
167: perror(name.c);
168: close(infd);
169: return;
170: }
171: }
172: else
173: {
174: /* open/create the index file */
175: index = fopen(PRSVINDEX, "a");
176: if (!index)
177: {
178: perror(PRSVINDEX);
179: exit(2);
180: }
181:
182: /* should be at the end of the file already, but MAKE SURE */
183: fseek(index, 0L, 2);
184:
185: /* create the recovery file in the PRESVDIR directory */
186: #if AMIGA
187: prsvdir = &PRSVDIR[strlen(PRSVDIR) - 1];
188: if (*prsvdir == '/' || *prsvdir == ':')
189: {
190: sprintf(outname, "%sp%ld", PRSVDIR, ftell(index));
191: }
192: else
193: #endif
194: sprintf(outname, "%s%cp%ld", PRSVDIR, SLASH, ftell(index));
195: outfp = fopen(outname, "w");
196: if (!outfp)
197: {
198: perror(outname);
199: close(infd);
200: fclose(index);
201: return;
202: }
203: }
204:
205: /* write the text of the file out to the recovery file */
206: for (i = 1; i < MAXBLKS && hdr.n[i]; i++)
207: {
208: lseek(infd, (long)hdr.n[i] * (long)BLKSIZE, 0);
209: if (read(infd, buf.c, BLKSIZE) != BLKSIZE)
210: {
211: /* messed up header */
212: fprintf(stderr, "%s: unrecoverable -- header trashed\n", name.c);
213: fclose(outfp);
214: close(infd);
215: if (index)
216: {
217: fclose(index);
218: }
219: unlink(outname);
220: return;
221: }
222: fputs(buf.c, outfp);
223: }
224:
225: /* add a line to the index file */
226: if (index)
227: {
228: fprintf(index, "%s %s\n", outname, name.c);
229: }
230:
231: /* close everything */
232: close(infd);
233: fclose(outfp);
234: if (index)
235: {
236: fclose(index);
237: }
238:
239: /* Are we doing this due to something more frightening than just
240: * a ":preserve" command?
241: */
242: if (*when)
243: {
244: /* send a mail message */
245: mail(ownername(tname), name.c, when);
246:
247: /* remove the temp file -- the editor has died already */
248: unlink(tname);
249: }
250: }
251:
252: void main(argc, argv)
253: int argc;
254: char **argv;
255: {
256: int i;
257: char *when = "the editor went away";
258:
259: #if MSDOS || TOS
260: /* expand any wildcards in the command line */
261: _ct_init("");
262: argv = wildexpand(&argc, argv);
263: #endif
264:
265: /* do we have a "when" argument? */
266: i = 1;
267: if (argc >= i + 1 && !strcmp(argv[i], "-R"))
268: {
269: rewrite_now = 1;
270: when = "";
271: i++;
272: #if ANY_UNIX
273: setuid(geteuid());
274: #endif
275: }
276: #if OSK
277: else
278: {
279: setuid(0);
280: }
281: #endif
282: if (argc >= i + 1 && argv[i][0] == '-')
283: {
284: when = argv[i] + 1;
285: i++;
286: }
287:
288: /* preserve everything we're supposed to */
289: while (i < argc)
290: {
291: preserve(argv[i], when);
292: i++;
293: }
294: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.