386BSD 0.1 development
[unix-history] / usr / src / usr.bin / elvisrecover / elvisrecover.c
CommitLineData
f5bcab4b
WJ
1/* elvrec.c */
2
3/* This file contains the file recovery program */
4
5/* Author:
6 * Steve Kirkendall
7 * 14407 SW Teal Blvd. #C
8 * Beaverton, OR 97005
9 * kirkenda@cs.pdx.edu
10 */
11
12
13#include <stdio.h>
14#include "config.h"
15#include "vi.h"
16
17void recover(basename, outname)
18 char *basename; /* the name of the file to recover */
19 char *outname; /* the name of the file to write to */
20{
21 char pathname[500]; /* full pathname of the file to recover */
22 char line[600]; /* a line from the /usr/preserve/Index file */
23 int ch; /* a character from the text being recovered */
24 FILE *from; /* the /usr/preserve file, or /usr/preserve/Index */
25 FILE *to; /* the user's text file */
26 char *ptr;
27#if OSK
28 int uid;
29#endif
30
31 /* convert basename to a full pathname */
32 if (basename)
33 {
34#ifndef CRUNCH
35# if MSDOS || TOS
36 if (!basename[0] || basename[1] != ':')
37# else
38 if (basename[0] != SLASH)
39# endif
40 {
41 ptr = getcwd(pathname, sizeof pathname);
42 if (ptr != pathname)
43 {
44 strcpy(pathname, ptr);
45 }
46 ptr = pathname + strlen(pathname);
47 *ptr++ = SLASH;
48 strcpy(ptr, basename);
49 }
50 else
51#endif
52 {
53 strcpy(pathname, basename);
54 }
55 }
56
57#if OSK
58 uid = getuid();
59 if(setuid(0))
60 exit(_errmsg(errno, "Can't set uid\n"));
61#endif
62 /* scan the /usr/preserve/Index file, for the *oldest* unrecovered
63 * version of this file.
64 */
65 from = fopen(PRSVINDEX, "r");
66 while (from && fgets(line, sizeof line, from))
67 {
68 /* strip off the newline from the end of the string */
69 line[strlen(line) - 1] = '\0';
70
71 /* parse the line into a "preserve" name and a "text" name */
72 for (ptr = line; *ptr != ' '; ptr++)
73 {
74 }
75 *ptr++ = '\0';
76
77 /* If the "preserve" file is missing, then ignore this line
78 * because it describes a file that has already been recovered.
79 */
80 if (access(line, 0) < 0)
81 {
82 continue;
83 }
84
85 /* are we looking for a specific file? */
86 if (basename)
87 {
88 /* quit if we found it */
89 if (!strcmp(ptr, pathname))
90 {
91 break;
92 }
93 }
94 else
95 {
96 /* list this file as "available for recovery" */
97 puts(ptr);
98 }
99 }
100
101 /* file not found? */
102 if (!basename || !from || feof(from))
103 {
104 if (from != NULL) fclose(from);
105 if (basename)
106 {
107 fprintf(stderr, "%s: no recovered file has that exact name\n", pathname);
108 }
109 return;
110 }
111 if (from != NULL) fclose(from);
112
113 /* copy the recovered text back into the user's file... */
114
115 /* open the /usr/preserve file for reading */
116 from = fopen(line, "r");
117 if (!from)
118 {
119 perror(line);
120 exit(2);
121 }
122
123#if ANY_UNIX
124 /* Be careful about user-id. We want to be running under the user's
125 * real id when we open/create the user's text file... but we want
126 * to be superuser when we delete the /usr/preserve file. For UNIX,
127 * we accomplish this by deleting the /usr/preserve file *now*,
128 * when it is open but before we've read it. Then we revert to the
129 * user's real id.
130 */
131 unlink(line);
132 setuid(getuid());
133#endif
134#if OSK
135 setuid(uid);
136#endif
137
138 if (outname == NULL) return;
139
140 /* open the user's file for writing */
141 to = fopen(outname, "w");
142 if (!to)
143 {
144 perror(ptr);
145 exit(2);
146 }
147
148 /* copy the text */
149 while ((ch = getc(from)) != EOF)
150 {
151 putc(ch, to);
152 }
153
154#if !ANY_UNIX
155#if OSK
156 fclose(from);
157 setuid(0);
158#endif
159 /* delete the /usr/preserve file */
160 unlink(line);
161#if OSK
162 setuid(uid);
163#endif
164#endif
165}
166
167main(argc, argv)
168 int argc;
169 char **argv;
170{
171 /* check arguments */
172 if (argc > 3)
173 {
174 fprintf(stderr, "usage: %s [preserved_file [recovery_file]]\n", argv[0]);
175 exit(1);
176 }
177
178 /* recover the requested file, or list recoverable files */
179 if (argc == 3)
180 {
181 /* recover the file, but write it to a different filename */
182 recover (argv[1], argv[2]);
183 }
184 else if (argc == 2)
185 {
186 /* recover the file */
187 recover(argv[1], argv[1]);
188 }
189 else
190 {
191 /* list the recoverable files */
192 recover((char *)0, (char *)0);
193 }
194
195 /* success! */
196 exit(0);
197}