]> git.cameronkatri.com Git - bsdgames-darwin.git/blob - rogue/save.c
Don't chown installed files or directories if UNPRIVILEGED is defined.
[bsdgames-darwin.git] / rogue / save.c
1 /* $NetBSD: save.c,v 1.5 1998/11/10 13:01:32 hubertf Exp $ */
2
3 /*
4 * Copyright (c) 1988, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Timothy C. Stoehr.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 */
38
39 #include <sys/cdefs.h>
40 #ifndef lint
41 #if 0
42 static char sccsid[] = "@(#)save.c 8.1 (Berkeley) 5/31/93";
43 #else
44 __RCSID("$NetBSD: save.c,v 1.5 1998/11/10 13:01:32 hubertf Exp $");
45 #endif
46 #endif /* not lint */
47
48 /*
49 * save.c
50 *
51 * This source herein may be modified and/or distributed by anybody who
52 * so desires, with the following restrictions:
53 * 1.) No portion of this notice shall be removed.
54 * 2.) Credit shall not be taken for the creation of this source.
55 * 3.) This code is not to be traded, sold, or used for personal
56 * gain or profit.
57 *
58 */
59
60 #include <stdio.h>
61 #include "rogue.h"
62
63 short write_failed = 0;
64 char *save_file = (char *) 0;
65
66 void
67 save_game()
68 {
69 char fname[64];
70
71 if (!get_input_line("file name?", save_file, fname, "game not saved",
72 0, 1)) {
73 return;
74 }
75 check_message();
76 message(fname, 0);
77 save_into_file(fname);
78 }
79
80 void
81 save_into_file(sfile)
82 const char *sfile;
83 {
84 FILE *fp;
85 int file_id;
86 char name_buffer[80];
87 char *hptr;
88 struct rogue_time rt_buf;
89
90 if (sfile[0] == '~') {
91 if ((hptr = md_getenv("HOME")) != NULL) {
92 (void) strcpy(name_buffer, hptr);
93 (void) strcat(name_buffer, sfile+1);
94 sfile = name_buffer;
95 }
96 }
97 if ( ((fp = fopen(sfile, "w")) == NULL) ||
98 ((file_id = md_get_file_id(sfile)) == -1)) {
99 message("problem accessing the save file", 0);
100 return;
101 }
102 md_ignore_signals();
103 write_failed = 0;
104 (void) xxx(1);
105 r_write(fp, (char *) &detect_monster, sizeof(detect_monster));
106 r_write(fp, (char *) &cur_level, sizeof(cur_level));
107 r_write(fp, (char *) &max_level, sizeof(max_level));
108 write_string(hunger_str, fp);
109 write_string(login_name, fp);
110 r_write(fp, (char *) &party_room, sizeof(party_room));
111 write_pack(&level_monsters, fp);
112 write_pack(&level_objects, fp);
113 r_write(fp, (char *) &file_id, sizeof(file_id));
114 rw_dungeon(fp, 1);
115 r_write(fp, (char *) &foods, sizeof(foods));
116 r_write(fp, (char *) &rogue, sizeof(fighter));
117 write_pack(&rogue.pack, fp);
118 rw_id(id_potions, fp, POTIONS, 1);
119 rw_id(id_scrolls, fp, SCROLS, 1);
120 rw_id(id_wands, fp, WANDS, 1);
121 rw_id(id_rings, fp, RINGS, 1);
122 r_write(fp, (char *) traps, (MAX_TRAPS * sizeof(trap)));
123 r_write(fp, (char *) is_wood, (WANDS * sizeof(boolean)));
124 r_write(fp, (char *) &cur_room, sizeof(cur_room));
125 rw_rooms(fp, 1);
126 r_write(fp, (char *) &being_held, sizeof(being_held));
127 r_write(fp, (char *) &bear_trap, sizeof(bear_trap));
128 r_write(fp, (char *) &halluc, sizeof(halluc));
129 r_write(fp, (char *) &blind, sizeof(blind));
130 r_write(fp, (char *) &confused, sizeof(confused));
131 r_write(fp, (char *) &levitate, sizeof(levitate));
132 r_write(fp, (char *) &haste_self, sizeof(haste_self));
133 r_write(fp, (char *) &see_invisible, sizeof(see_invisible));
134 r_write(fp, (char *) &detect_monster, sizeof(detect_monster));
135 r_write(fp, (char *) &wizard, sizeof(wizard));
136 r_write(fp, (char *) &score_only, sizeof(score_only));
137 r_write(fp, (char *) &m_moves, sizeof(m_moves));
138 md_gct(&rt_buf);
139 rt_buf.second += 10; /* allow for some processing time */
140 r_write(fp, (char *) &rt_buf, sizeof(rt_buf));
141 fclose(fp);
142
143 if (write_failed) {
144 (void) md_df(sfile); /* delete file */
145 } else {
146 clean_up("");
147 }
148 }
149
150 void
151 restore(fname)
152 const char *fname;
153 {
154 FILE *fp;
155 struct rogue_time saved_time, mod_time;
156 char buf[4];
157 char tbuf[40];
158 int new_file_id, saved_file_id;
159
160 fp = NULL;
161 if ( ((new_file_id = md_get_file_id(fname)) == -1) ||
162 ((fp = fopen(fname, "r")) == NULL)) {
163 clean_up("cannot open file");
164 }
165 if (md_link_count(fname) > 1) {
166 clean_up("file has link");
167 }
168 (void) xxx(1);
169 r_read(fp, (char *) &detect_monster, sizeof(detect_monster));
170 r_read(fp, (char *) &cur_level, sizeof(cur_level));
171 r_read(fp, (char *) &max_level, sizeof(max_level));
172 read_string(hunger_str, fp);
173
174 (void) strcpy(tbuf, login_name);
175 read_string(login_name, fp);
176 if (strcmp(tbuf, login_name)) {
177 clean_up("you're not the original player");
178 }
179
180 r_read(fp, (char *) &party_room, sizeof(party_room));
181 read_pack(&level_monsters, fp, 0);
182 read_pack(&level_objects, fp, 0);
183 r_read(fp, (char *) &saved_file_id, sizeof(saved_file_id));
184 if (new_file_id != saved_file_id) {
185 clean_up("sorry, saved game is not in the same file");
186 }
187 rw_dungeon(fp, 0);
188 r_read(fp, (char *) &foods, sizeof(foods));
189 r_read(fp, (char *) &rogue, sizeof(fighter));
190 read_pack(&rogue.pack, fp, 1);
191 rw_id(id_potions, fp, POTIONS, 0);
192 rw_id(id_scrolls, fp, SCROLS, 0);
193 rw_id(id_wands, fp, WANDS, 0);
194 rw_id(id_rings, fp, RINGS, 0);
195 r_read(fp, (char *) traps, (MAX_TRAPS * sizeof(trap)));
196 r_read(fp, (char *) is_wood, (WANDS * sizeof(boolean)));
197 r_read(fp, (char *) &cur_room, sizeof(cur_room));
198 rw_rooms(fp, 0);
199 r_read(fp, (char *) &being_held, sizeof(being_held));
200 r_read(fp, (char *) &bear_trap, sizeof(bear_trap));
201 r_read(fp, (char *) &halluc, sizeof(halluc));
202 r_read(fp, (char *) &blind, sizeof(blind));
203 r_read(fp, (char *) &confused, sizeof(confused));
204 r_read(fp, (char *) &levitate, sizeof(levitate));
205 r_read(fp, (char *) &haste_self, sizeof(haste_self));
206 r_read(fp, (char *) &see_invisible, sizeof(see_invisible));
207 r_read(fp, (char *) &detect_monster, sizeof(detect_monster));
208 r_read(fp, (char *) &wizard, sizeof(wizard));
209 r_read(fp, (char *) &score_only, sizeof(score_only));
210 r_read(fp, (char *) &m_moves, sizeof(m_moves));
211 r_read(fp, (char *) &saved_time, sizeof(saved_time));
212
213 if (fread(buf, sizeof(char), 1, fp) > 0) {
214 clear();
215 clean_up("extra characters in file");
216 }
217
218 md_gfmt(fname, &mod_time); /* get file modification time */
219
220 if (has_been_touched(&saved_time, &mod_time)) {
221 clear();
222 clean_up("sorry, file has been touched");
223 }
224 if ((!wizard) && !md_df(fname)) {
225 clean_up("cannot delete file");
226 }
227 msg_cleared = 0;
228 ring_stats(0);
229 fclose(fp);
230 }
231
232 void
233 write_pack(pack, fp)
234 const object *pack;
235 FILE *fp;
236 {
237 object t;
238
239 while ((pack = pack->next_object) != NULL) {
240 r_write(fp, (const char *) pack, sizeof(object));
241 }
242 t.ichar = t.what_is = 0;
243 r_write(fp, (const char *) &t, sizeof(object));
244 }
245
246 void
247 read_pack(pack, fp, is_rogue)
248 object *pack;
249 FILE *fp;
250 boolean is_rogue;
251 {
252 object read_obj, *new_obj;
253
254 for (;;) {
255 r_read(fp, (char *) &read_obj, sizeof(object));
256 if (read_obj.ichar == 0) {
257 pack->next_object = (object *) 0;
258 break;
259 }
260 new_obj = alloc_object();
261 *new_obj = read_obj;
262 if (is_rogue) {
263 if (new_obj->in_use_flags & BEING_WORN) {
264 do_wear(new_obj);
265 } else if (new_obj->in_use_flags & BEING_WIELDED) {
266 do_wield(new_obj);
267 } else if (new_obj->in_use_flags & (ON_EITHER_HAND)) {
268 do_put_on(new_obj,
269 ((new_obj->in_use_flags & ON_LEFT_HAND) ? 1 : 0));
270 }
271 }
272 pack->next_object = new_obj;
273 pack = new_obj;
274 }
275 }
276
277 void
278 rw_dungeon(fp, rw)
279 FILE *fp;
280 boolean rw;
281 {
282 short i, j;
283 char buf[DCOLS];
284
285 for (i = 0; i < DROWS; i++) {
286 if (rw) {
287 r_write(fp, (char *) dungeon[i], (DCOLS * sizeof(dungeon[0][0])));
288 for (j = 0; j < DCOLS; j++) {
289 buf[j] = mvinch(i, j);
290 }
291 r_write(fp, buf, DCOLS);
292 } else {
293 r_read(fp, (char *) dungeon[i], (DCOLS * sizeof(dungeon[0][0])));
294 r_read(fp, buf, DCOLS);
295 for (j = 0; j < DCOLS; j++) {
296 mvaddch(i, j, buf[j]);
297 }
298 }
299 }
300 }
301
302 void
303 rw_id(id_table, fp, n, wr)
304 struct id id_table[];
305 FILE *fp;
306 int n;
307 boolean wr;
308 {
309 short i;
310
311 for (i = 0; i < n; i++) {
312 if (wr) {
313 r_write(fp, (const char *) &(id_table[i].value), sizeof(short));
314 r_write(fp, (const char *) &(id_table[i].id_status),
315 sizeof(unsigned short));
316 write_string(id_table[i].title, fp);
317 } else {
318 r_read(fp, (char *) &(id_table[i].value), sizeof(short));
319 r_read(fp, (char *) &(id_table[i].id_status),
320 sizeof(unsigned short));
321 read_string(id_table[i].title, fp);
322 }
323 }
324 }
325
326 void
327 write_string(s, fp)
328 char *s;
329 FILE *fp;
330 {
331 short n;
332
333 n = strlen(s) + 1;
334 xxxx(s, n);
335 r_write(fp, (char *) &n, sizeof(short));
336 r_write(fp, s, n);
337 }
338
339 void
340 read_string(s, fp)
341 char *s;
342 FILE *fp;
343 {
344 short n;
345
346 r_read(fp, (char *) &n, sizeof(short));
347 r_read(fp, s, n);
348 xxxx(s, n);
349 }
350
351 void
352 rw_rooms(fp, rw)
353 FILE *fp;
354 boolean rw;
355 {
356 short i;
357
358 for (i = 0; i < MAXROOMS; i++) {
359 rw ? r_write(fp, (char *) (rooms + i), sizeof(room)) :
360 r_read(fp, (char *) (rooms + i), sizeof(room));
361 }
362 }
363
364 void
365 r_read(fp, buf, n)
366 FILE *fp;
367 char *buf;
368 int n;
369 {
370 if (fread(buf, sizeof(char), n, fp) != n) {
371 clean_up("read() failed, don't know why");
372 }
373 }
374
375 void
376 r_write(fp, buf, n)
377 FILE *fp;
378 const char *buf;
379 int n;
380 {
381 if (!write_failed) {
382 if (fwrite(buf, sizeof(char), n, fp) != n) {
383 message("write() failed, don't know why", 0);
384 sound_bell();
385 write_failed = 1;
386 }
387 }
388 }
389
390 boolean
391 has_been_touched(saved_time, mod_time)
392 const struct rogue_time *saved_time, *mod_time;
393 {
394 if (saved_time->year < mod_time->year) {
395 return(1);
396 } else if (saved_time->year > mod_time->year) {
397 return(0);
398 }
399 if (saved_time->month < mod_time->month) {
400 return(1);
401 } else if (saved_time->month > mod_time->month) {
402 return(0);
403 }
404 if (saved_time->day < mod_time->day) {
405 return(1);
406 } else if (saved_time->day > mod_time->day) {
407 return(0);
408 }
409 if (saved_time->hour < mod_time->hour) {
410 return(1);
411 } else if (saved_time->hour > mod_time->hour) {
412 return(0);
413 }
414 if (saved_time->minute < mod_time->minute) {
415 return(1);
416 } else if (saved_time->minute > mod_time->minute) {
417 return(0);
418 }
419 if (saved_time->second < mod_time->second) {
420 return(1);
421 }
422 return(0);
423 }