1 /* omega (c) 1987,1988,1989 by Laurence Raphael Brothers */
2 /* file.c */
3 /* functions with file access in them. Also some direct calls to
4    curses functions */
5 
6 #ifdef MSDOS_SUPPORTED_ANTIQUE
7 # include "curses.h"
8 #else
9 # ifdef AMIGA
10 #  include <curses210.h>
11 # else
12 #  ifdef __FreeBSD__
13 #   include <ncurses.h>
14 #  else
15 #   include <curses.h>
16 #  endif
17 # endif
18 # include <sys/types.h>
19 # include <unistd.h>
20 # include <sys/file.h>
21 # include <fcntl.h>
22 # include <errno.h>
23 #endif
24 
25 #include "glob.h"
26 
checkfopen(filestring,optionstring)27 FILE *checkfopen(filestring,optionstring)
28 char *filestring,*optionstring;
29 {
30   FILE *fd;
31   char response;
32 
33   change_to_game_perms();
34   fd = fopen(filestring,optionstring);
35   clearmsg();
36   while (fd == NULL) {
37     print3("Warning! Error opening file:");
38     nprint3(filestring);
39     print1(" Abort or Retry? [ar] ");
40     do response = (char) mcigetc();
41     while ((response != 'a') && (response != 'r'));
42     if (response == 'r') fd = fopen(filestring,optionstring);
43     else {
44       print2("Sorry 'bout that.... Saving character, then quitting.");
45       morewait();
46       save(optionp(COMPRESS_OPTION), TRUE);
47       endgraf();
48       exit(0);
49     }
50   }
51   return(fd);
52 }
53 
commandlist()54 void commandlist()
55 {
56   strcpy(Str1,Omegalib);
57   if (Current_Environment == E_COUNTRYSIDE)
58     strcat(Str1,"help13.txt");
59   else strcat(Str1,"help12.txt");
60   displayfile(Str1);
61   xredraw();
62 }
63 
64 
user_intro()65 void user_intro()
66 {
67   strcpy(Str1,Omegalib);
68   strcat(Str1,"intro.txt");
69   displaycryptfile(Str1);
70   xredraw();
71 }
72 
show_license()73 void show_license()
74 {
75   strcpy(Str1,Omegalib);
76   strcat(Str1,"license.txt");
77   displayfile(Str1);
78   xredraw();
79 }
80 
81 
82 
abyss_file()83 void abyss_file()
84 {
85   strcpy(Str1,Omegalib);
86   strcat(Str1,"abyss.txt");
87   displaycryptfile(Str1);
88 }
89 
90 
91 
92 
inv_help()93 void inv_help()
94 {
95   strcpy(Str1,Omegalib);
96   strcat(Str1,"help3.txt");
97   displayfile(Str1);
98   xredraw();
99 }
100 
101 
102 
combat_help()103 void combat_help()
104 {
105   strcpy(Str1,Omegalib);
106   strcat(Str1,"help5.txt");
107   displayfile(Str1);
108   menuclear();
109 }
110 
111 
112 
113 
cityguidefile()114 void cityguidefile()
115 {
116   strcpy(Str1,Omegalib);
117   strcat(Str1,"scroll2.txt");
118   displaycryptfile(Str1);
119   xredraw();
120 }
121 
122 
wishfile()123 void wishfile()
124 {
125   strcpy(Str1,Omegalib);
126   strcat(Str1,"scroll3.txt");
127   displaycryptfile(Str1);
128   xredraw();
129 }
130 
adeptfile()131 void adeptfile()
132 {
133   strcpy(Str1,Omegalib);
134   strcat(Str1,"scroll4.txt");
135   displaycryptfile(Str1);
136   xredraw();
137 }
138 
theologyfile()139 void theologyfile()
140 {
141   strcpy(Str1,Omegalib);
142   strcat(Str1,"scroll1.txt");
143   displaycryptfile(Str1);
144   xredraw();
145 }
146 
147 
showmotd()148 void showmotd()
149 {
150   strcpy(Str1,Omegalib);
151   strcat(Str1,"motd.txt");
152   displayfile(Str1);
153 }
154 
155 
lock_score_file()156 void lock_score_file()
157 {
158 #ifndef MSDOS
159     int lock, attempts, thispid, lastpid = 0;
160     FILE *lockfile;
161 
162     strcpy(Str1,Omegalib);
163     strcat(Str1,"omega.hi.lock");
164     do
165     {
166 	lock = open(Str1, O_CREAT|O_EXCL, 0600);	/* create lock file */
167 	if (lock < 0 && errno == EEXIST)
168 	{
169 	    lockfile = fopen(Str1, "rb");
170 	    if (lockfile)
171 	    {
172 		fscanf(lockfile, "%d", &thispid);
173 		fclose(lockfile);
174 		if (thispid != lastpid)
175 		    attempts = 0;
176 		lastpid = thispid;
177 	    }
178 	    attempts++;
179 	    if (attempts > 10)	/* assume that lock file has been abandoned */
180 		unlink(Str1);	/* so we unlink it ourselves - ugly...	*/
181 	    else
182 		sleep(2);
183 	}
184 	else if (lock < 0)	/* oops - something very wrong */
185 	    return;
186     } while (lock < 0);
187     sprintf(Str1, "%d", getpid());
188     write(lock, Str1, strlen(Str1));
189     close(lock);
190 #endif
191 }
192 
unlock_score_file()193 void unlock_score_file()
194 {
195 #ifndef MSDOS
196     strcpy(Str1,Omegalib);
197     strcat(Str1,"omega.hi.lock");
198     unlink(Str1);
199 #endif
200 }
201 
showscores()202 void showscores()
203 {
204   FILE *fd;
205   int i;
206 
207   lock_score_file();
208   strcpy(Str1,Omegalib);
209   strcat(Str1,"omega.hi");
210   fd = checkfopen(Str1,"rb");
211   filescanstring(fd,Hiscorer);
212   filescanstring(fd,Hidescrip);
213   fscanf(fd,"%ld %d %d\n",&Hiscore,&Hilevel,&Hibehavior);
214   for(i=1;i<7;i++) {
215     filescanstring(fd,Priest[i]);
216     fscanf(fd,"%d %d\n",&(Priestlevel[i]),&(Priestbehavior[i]));
217   }
218   filescanstring(fd,Shadowlord);
219   fscanf(fd,"%d %d\n",&Shadowlordlevel,&Shadowlordbehavior);
220   filescanstring(fd,Commandant);
221   fscanf(fd,"%d %d\n",&Commandantlevel,&Commandantbehavior);
222   filescanstring(fd,Archmage);
223   fscanf(fd,"%d %d\n",&Archmagelevel,&Archmagebehavior);
224   filescanstring(fd,Prime);
225   fscanf(fd,"%d %d\n",&Primelevel,&Primebehavior);
226   filescanstring(fd,Champion);
227   fscanf(fd,"%d %d\n",&Championlevel,&Championbehavior);
228   filescanstring(fd,Duke);
229   fscanf(fd,"%d %d\n",&Dukelevel,&Dukebehavior);
230   filescanstring(fd,Chaoslord);
231   fscanf(fd,"%d %d %d\n",&Chaoslordlevel,&Chaos,&Chaoslordbehavior);
232   filescanstring(fd,Lawlord);
233   fscanf(fd,"%d %d %d\n",&Lawlordlevel,&Law,&Lawlordbehavior);
234   filescanstring(fd,Justiciar);
235   fscanf(fd,"%d %d\n",&Justiciarlevel,&Justiciarbehavior);
236   fclose(fd);
237   unlock_score_file();
238   clear();
239   printw("High Score: %ld",Hiscore);
240   printw(", by %s (%s)",Hiscorer,levelname(Hilevel));
241   printw("\n%s\n",Hidescrip);
242   printw("\nLord of Chaos: %s (%s)",Chaoslord,levelname(Chaoslordlevel));
243   printw("\nLord of Law: %s (%s)",Lawlord,levelname(Lawlordlevel));
244   printw("\n\nDuke of Rampart:              ");
245   printw("%s (%s)",Duke,levelname(Dukelevel));
246   printw("\nJusticiar:                    ");
247   printw("%s (%s)",Justiciar,levelname(Justiciarlevel));
248   printw("\nCommandant:                   ");
249   printw("%s (%s)",Commandant,levelname(Commandantlevel));
250   printw("\nChampion:                     ");
251   printw("%s (%s)",Champion,levelname(Championlevel));
252   printw("\nArchmage:                     ");
253   printw("%s (%s)",Archmage,levelname(Archmagelevel));
254   printw("\nPrime Sorceror:               ");
255   printw("%s (%s)",Prime,levelname(Primelevel));
256   printw("\nShadowlord:                   ");
257   printw("%s (%s)",Shadowlord,levelname(Shadowlordlevel));
258   printw("\n\nHigh Priests:");
259   printw("\n of Odin:                     ");
260   printw("%s (%s)",Priest[ODIN],levelname(Priestlevel[ODIN]));
261   printw("\n of Set:                      ");
262   printw("%s (%s)",Priest[SET],levelname(Priestlevel[SET]));
263   printw("\n of Athena:                   ");
264   printw("%s (%s)",Priest[ATHENA],levelname(Priestlevel[ATHENA]));
265   printw("\n of Hecate:                   ");
266   printw("%s (%s)",Priest[HECATE],levelname(Priestlevel[HECATE]));
267   printw("\n of the Lords of Destiny:     ");
268   printw("%s (%s)",Priest[DESTINY],levelname(Priestlevel[DESTINY]));
269   printw("\nThe ArchDruid:                ");
270   printw("%s (%s)",Priest[DRUID],levelname(Priestlevel[DRUID]));
271   printw("\n\nHit any key to continue.");
272   refresh();
273   wgetch(stdscr);
274   clear_screen();
275 }
276 
277 /* Writes a new high-score file, with the nominated npc as whatever it is */
278 /* in this particular game, but the others as they appear in the file. */
save_hiscore_npc(npc)279 void save_hiscore_npc(npc)
280 int npc;
281 {
282   FILE *infile, *outfile;
283   char buffer[80];
284   int i;
285 
286   if (gamestatusp(CHEATED))
287       return;
288   lock_score_file();
289   strcpy(Str1,Omegalib);
290   strcat(Str1,"omega.hi");
291   infile = checkfopen(Str1,"rb");
292   strcpy(Str2,Omegalib);
293 #ifdef MSDOS
294   strcat(Str2,"omegahi.new");	/* stupid 8.3 msdos filename limit */
295 #else
296   strcat(Str2,"omega.hi.new");
297 #endif
298   outfile = checkfopen(Str2,"wb");
299   for (i = 0; i < 16; i++) {
300     if (npc == i) {
301       switch (i) {
302 	case 0:
303 	  fprintf(outfile,"%s\n%s\n%ld %d %d\n",Hiscorer, Hidescrip, Hiscore,
304 	    Hilevel, Hibehavior);
305 	  break;
306 	case 1: case 2: case 3: case 4: case 5: case 6:
307 	  fprintf(outfile,"%s\n%d %d\n", Priest[i], Priestlevel[i],
308 	    Priestbehavior[i]);
309 	  break;
310 	case 7:
311 	  fprintf(outfile,"%s\n%d %d\n", Shadowlord, Shadowlordlevel,
312 	    Shadowlordbehavior);
313 	  break;
314 	case 8:
315 	  fprintf(outfile,"%s\n%d %d\n", Commandant, Commandantlevel,
316 	    Commandantbehavior);
317 	  break;
318 	case 9:
319 	  fprintf(outfile,"%s\n%d %d\n", Archmage, Archmagelevel,
320 	    Archmagebehavior);
321 	  break;
322 	case 10:
323 	  fprintf(outfile,"%s\n%d %d\n", Prime, Primelevel, Primebehavior);
324 	  break;
325 	case 11:
326 	  fprintf(outfile,"%s\n%d %d\n", Champion, Championlevel,
327 	    Championbehavior);
328 	  break;
329 	case 12:
330 	  fprintf(outfile,"%s\n%d %d\n", Duke, Dukelevel, Dukebehavior);
331 	  break;
332 	case 13:
333 	  fprintf(outfile,"%s\n%d %d %d\n",Chaoslord, Chaoslordlevel, Chaos,
334 	    Chaoslordbehavior);
335 	  break;
336 	case 14:
337 	  fprintf(outfile,"%s\n%d %d %d\n", Lawlord, Lawlordlevel, Law,
338 	    Lawlordbehavior);
339 	  break;
340 	case 15:
341 	  fprintf(outfile,"%s\n%d %d\n", Justiciar, Justiciarlevel,
342 	    Justiciarbehavior);
343 	  break;
344       }
345     }
346     if (i == 0) {
347       fgets(buffer, 80, infile);
348       if (i != npc)
349 	fputs(buffer, outfile);
350     }
351     fgets(buffer, 80, infile);
352     if (i != npc)
353       fputs(buffer, outfile);
354     fgets(buffer, 80, infile);
355     if (i != npc)
356       fputs(buffer, outfile);
357   }
358   fclose(infile);
359   fclose(outfile);
360   unlink(Str1);
361 #if defined(MSDOS) || defined(AMIGA)
362   rename(Str2, Str1);
363 #else
364   link(Str2, Str1);
365   unlink(Str2);	/* renames, but sys-V doesn't have rename()... */
366 #endif
367   unlock_score_file();
368 }
369 
checkhigh(descrip,behavior)370 void checkhigh(descrip,behavior)
371 char *descrip;
372 int behavior;
373 {
374   long points;
375 
376   if (FixedPoints > 0) points = FixedPoints;
377   else points = calc_points();
378   if (!gamestatusp(CHEATED)) {
379     if (Hiscore < points) {
380       strcpy(Hiscorer, Player.name);
381       strcpy(Hidescrip, descrip);
382       Hiscore = points;
383       Hilevel = Player.level;
384       Hibehavior = behavior;
385       save_hiscore_npc(0);
386       mprint("Yow! A new high score!");
387       morewait();
388     }
389     if (Player.alignment < Chaos) {
390       strcpy(Chaoslord, Player.name);
391       Chaoslordlevel = Player.level;
392       Chaos = Player.alignment;
393       Chaoslordbehavior = behavior;
394       save_hiscore_npc(13);
395       mprint("Criminy! A new Lord of Chaos!");
396       morewait();
397     }
398     if (Player.alignment > Law) {
399       strcpy(Lawlord, Player.name);
400       Lawlordlevel = Player.level;
401       Law = Player.alignment;
402       Lawlordbehavior = behavior;
403       save_hiscore_npc(14);
404       mprint("Gosh! A new Lord of Law!");
405       morewait();
406     }
407   }
408 }
409 
extendlog(descrip,lifestatus)410 void extendlog(descrip,lifestatus)
411 char *descrip;
412 int lifestatus;
413 {
414   FILE *fd;
415   int npcbehavior;
416 
417   if ((Player.level > 0) && (! gamestatusp(CHEATED))) {
418     change_to_game_perms();
419     npcbehavior=fixnpc(lifestatus);
420     checkhigh(descrip,npcbehavior);
421     strcpy(Str1,Omegalib);
422     strcat(Str1,"omega.log");
423     fd = checkfopen(Str1,"a");
424     fprintf(fd, " %d %d %d %s\n", lifestatus, Player.level, npcbehavior,
425       Player.name);
426     fclose(fd);
427   }
428 }
429 
430 
431 
432 
433 
434 #ifndef MSDOS
435 /* reads a string from a file. If it is a line with more than 80 char's,
436    then remainder of line to \n is consumed */
filescanstring(fd,fstr)437 void filescanstring(fd,fstr)
438 FILE *fd;
439 char *fstr;
440 {
441   int i= -1;
442   int byte='x';
443   while ((i<80) && (byte != '\n') && (byte != EOF)) {
444     i++;
445     byte=fgetc(fd);
446     fstr[i] = byte;
447   }
448   if (byte != '\n')
449     while((byte!='\n') && (byte != EOF))
450       byte=fgetc(fd);
451   fstr[i]=0;
452 }
453 #endif
454 
455 #ifdef MSDOS
test_file_access(file_name,mode)456 int test_file_access(file_name, mode)
457 char *file_name;
458 char mode;
459 {
460     FILE *fd;
461 
462     if (mode == 'r')
463 	fd = fopen(file_name, "r");
464     else
465 	fd = fopen(file_name, "r+");
466     if (!fd)
467 	return 0;
468     fclose(fd);
469     return 1;
470 }
471 #else
test_file_access(file_name,mode)472 int test_file_access(file_name, mode)
473 char *file_name;
474 char mode;
475 {
476     int fd;
477 
478     if (mode == 'r')
479 	fd = open(file_name, O_RDONLY, 0);
480     else
481 	fd = open(file_name, O_RDWR, 0);
482     if (fd < 0)
483 	return 0;
484     close(fd);
485     return 1;
486 }
487 #endif
488 
489 char *required_file_list[] =
490 {
491   "city.dat", "country.dat", "dlair.dat", "misle.dat", "court.dat",
492   "speak.dat", "temple.dat", "abyss.dat", "village1.dat", "village2.dat",
493   "village3.dat", "village4.dat", "village5.dat", "village6.dat",
494   "home1.dat", "home2.dat", "home3.dat", "arena.dat", "maze1.dat",
495   "maze2.dat", "maze3.dat", "maze4.dat", "omega.hi", "omega.log", "motd.txt",
496   "license.txt", "circle.dat", NULL
497 };
498 
499 char *optional_file_list[] =
500 {
501   "help1.txt", "help2.txt", "help3.txt", "help4.txt", "help5.txt",
502   "help6.txt", "help7.txt", "help8.txt", "help9.txt", "help10.txt",
503   "help11.txt", "help12.txt", "help13.txt", "abyss.txt", "scroll1.txt",
504   "scroll2.txt", "scroll3.txt", "scroll4.txt", NULL
505 };
506 
507 /* Checks existence of omega data files */
508 /* Returns 1 if OK, 0 if impossible to run, -1 if possible but not OK */
filecheck()509 int filecheck()
510 {
511     int impossible=FALSE,badbutpossible=FALSE;
512     int endpos;
513     int file;
514 
515     strcpy(Str1, Omegalib);
516     endpos = strlen(Str1);
517     for (file = 0; required_file_list[file]; file++)
518     {
519 	strcpy(&(Str1[endpos]), required_file_list[file]);
520 	if ((strcmp(required_file_list[file], "omega.hi") == 0 ||
521 	    strcmp(required_file_list[file], "omega.log") == 0) &&
522 	    test_file_access(Str1, 'w') == 0)
523 	{
524 	    impossible = TRUE;
525 	    printf("\nError! File not appendable or accessible: %s", Str1);
526 	}
527 	else if (test_file_access(Str1, 'r') == 0)
528 	{
529 	    impossible = TRUE;
530 	    printf("\nError! File not accessible: %s", Str1);
531 	}
532     }
533     for (file = 0; optional_file_list[file]; file++)
534     {
535 	strcpy(&(Str1[endpos]), optional_file_list[file]);
536 	if (test_file_access(Str1, 'r') == 0)
537 	{
538 	    badbutpossible = TRUE;
539 	    printf("\nWarning! File not accessible: %s", Str1);
540 	}
541     }
542     if (impossible) {
543 	printf("\nFurther execution is impossible. Sorry.");
544 	if (strcmp(Omegalib, OMEGALIB))
545 	  printf("\nEnvironment variable OMEGALIB badly set\n");
546 	else {
547 	  printf("\nOMEGALIB may be badly #defined in defs.h\n");
548 #ifndef FIXED_OMEGALIB
549 	  printf("\nYou can set the environment variable OMEGALIB to\n");
550 	  printf("the location of the omegalib directory.\n");
551 #endif
552 	}
553 	return(0);
554     }
555     else if (badbutpossible) {
556 	printf("\nFurther execution may cause anomalous behavior.");
557 	printf("\nContinue anyhow? [yn] ");
558 	if (getchar()=='y') return(-1);
559 	else return(0);
560     }
561     else return(1);
562 }
563 
564 /* display a file given a string name of file */
displayfile(filestr)565 void displayfile(filestr)
566 char *filestr;
567 {
568   FILE *fd = checkfopen(filestr,"r");
569   int c,d=' ';
570   int x,y;
571   clear();
572   refresh();
573   c = fgetc(fd);
574   while ((c != EOF)&&((char) d != 'q')&&((char) d!=ESCAPE)) {
575     getyx(stdscr,y,x);
576     if (y > ScreenLength) {
577       standout();
578       printw("\n-More-");
579       standend();
580       refresh();
581       d = wgetch(stdscr);
582       clear();
583     }
584     printw("%c",(char) c);
585     c = fgetc(fd);
586   }
587   if (((char) d != 'q')&&((char) d!=ESCAPE)) {
588     standout();
589     printw("\n-Done-");
590     standend();
591     refresh();
592     getch();
593   }
594   clear();
595   refresh();
596   fclose(fd);
597 }
598 
599 /* display a file given a string name of file */
displaycryptfile(filestr)600 void displaycryptfile(filestr)
601 char *filestr;
602 {
603   FILE *fd = checkfopen(filestr,"rb");
604   int c,d=' ';
605   int x,y;
606   char key = 100;
607 
608   clear();
609   refresh();
610   c = fgetc(fd);
611   while ((c != EOF)&&((char) d != 'q')&&((char) d!=ESCAPE)) {
612     getyx(stdscr,y,x);
613     if (y > ScreenLength) {
614       standout();
615       printw("\n-More-");
616       standend();
617       refresh();
618       d = wgetch(stdscr);
619       clear();
620     }
621     key = ((unsigned char) c)^key;
622     printw("%c", key);
623     c = fgetc(fd);
624   }
625   if (((char) d != 'q')&&((char) d!=ESCAPE)) {
626     standout();
627     printw("\n-Done-");
628     standend();
629     refresh();
630     getch();
631   }
632   clear();
633   refresh();
634   fclose(fd);
635 }
636 
637 /* copy a file given a string name of file */
copyfile(srcstr)638 void copyfile(srcstr)
639 char *srcstr;
640 {
641   char deststr[80];
642   char buffer[STRING_LEN];
643   FILE *in, *out;
644 
645   print1("Enter name of file to create: ");
646   strcpy(deststr,msgscanstring());
647   if (strlen(deststr) == 0) {
648     print2("Aborting...");
649     morewait();
650     return;
651   }
652   in = checkfopen(srcstr, "rb");
653   change_to_user_perms();
654   out = fopen(deststr, "wb");
655   if (!out) {
656     sprintf(buffer, "Unable to write to file %s - Aborting.", deststr);
657     print2(buffer);
658     change_to_game_perms();
659     morewait();
660     fclose(in);
661     return;
662   }
663   print2("Copying file....");
664   while (fgets(buffer, STRING_LEN, in))
665     fputs(buffer, out);
666   fclose(in);
667   fclose(out);
668   change_to_game_perms();
669   print3("Done.");
670 }
671 
672