comparison src/main.c @ 4:aa38447a4b21

First entry of Paradise Server 2.9 patch 10 Beta
author darius
date Sat, 06 Dec 1997 04:37:03 +0000
parents
children
comparison
equal deleted inserted replaced
3:cafa94d86546 4:aa38447a4b21
1 /*--------------------------------------------------------------------------
2 NETREK II -- Paradise
3
4 Permission to use, copy, modify, and distribute this software and its
5 documentation, or any derivative works thereof, for any NON-COMMERCIAL
6 purpose and without fee is hereby granted, provided that this copyright
7 notice appear in all copies. No representations are made about the
8 suitability of this software for any purpose. This software is provided
9 "as is" without express or implied warranty.
10
11 Xtrek Copyright 1986 Chris Guthrie
12 Netrek (Xtrek II) Copyright 1989 Kevin P. Smith
13 Scott Silvey
14 Paradise II (Netrek II) Copyright 1993 Larry Denys
15 Kurt Olsen
16 Brandon Gillespie
17 --------------------------------------------------------------------------*/
18 char binary[] = "@(#)ntserv";
19
20 #include "config.h"
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <sys/types.h>
25 #include <signal.h>
26 #include <setjmp.h>
27 #include <pwd.h>
28 #include <sys/time.h>
29 #include <sys/wait.h>
30 #include <sys/resource.h>
31 #include <unistd.h>
32
33 #include "defs.h"
34 #include "struct.h"
35 #include "data.h"
36 #include "packets.h"
37 #include "shmem.h"
38 #include "path.h"
39
40 #if 0
41 #define D(s) do { s } while(0)
42 #else
43 #define D(s)
44 #endif
45
46
47 #if 0
48 jmp_buf env;
49 #endif
50
51 int startTkills, startTlosses, startTarms, startTplanets, startTticks;
52 char start_login[16]; /* change 1/25/91 TC */
53 char start_name[16]; /* change 1/25/91 TC */
54 int goAway = 0; /* change 4/14/91 TC */
55 int ignored[MAXPLAYER]; /* change 7/24/91 TC */
56
57 int overload = 0; /* global 7/31/91 TC */
58 /* overload indicates a request for a reserved slot */
59
60 int indie = 0; /* always be indie 8/28/91 TC */
61
62
63 extern void load_time_access();
64 void printntservUsage();
65 extern pid_t getpid();
66 extern int connectToClient();
67 extern int checkSocket();
68 extern int initClientData();
69 extern int socketPause();
70 extern int readFromClient();
71 extern int checkVersion();
72 extern int findslot();
73 extern void updateSelf();
74 extern void updateShips();
75 extern void updatePlanets();
76 extern void updateTerrain();
77 extern void flushSockBuf();
78 extern int getname();
79 extern int sendShipCap();
80 extern int logEntry();
81 extern int getEntry();
82 void printStats();
83 void exitGame();
84 #if defined(sparc) && !defined(SVR4)
85 int atexitfunc( /* int, caddr_t */ );
86 #else
87 void atexitfunc();
88 #endif
89 extern void (*r_signal()) ();
90 extern int enter();
91 extern int input();
92 extern int setitimer();
93 extern int pmessage2();
94 extern int savestats();
95 extern void move_player();
96 extern int sendMotdLine();
97 extern int time_access();
98 void doMotdPics();
99 extern int numPlanets();
100 extern int sendMotdPic();
101 extern int ParseXbmFile();
102
103 int
104 main(argc, argv)
105 int argc;
106 char **argv;
107 {
108 int intrupt();
109 char *getenv();
110 int team, s_type;
111 int pno;
112 int usage = 0; /* Flag saying tell usage */
113 int errorc = 0; /* Error count */
114 char *errorv[5]; /* Error Vector (cannot have more than 5) */
115 char *name, *ptr;
116 int reaper();
117 int callHost = 0;
118 long starttime;
119 enum HomeAway homeaway = NEITHER;
120 int observer = 0;
121
122 argv0 = argv[0];
123
124 pno = time(NULL);
125
126
127 /* load_time_acess - read in the hours file, Larry's. */
128
129 load_time_access();
130
131 name = *argv++;
132 argc--;
133 if ((ptr = strrchr(name, '/')) != NULL)
134 name = ptr + 1;
135 while (*argv)
136 {
137 if (**argv == '-')
138 ++* argv;
139 else
140 break;
141
142 argc--;
143 ptr = *argv++;
144 while (*ptr)
145 {
146 switch (*ptr)
147 {
148 case 'u': /* for old times sake */
149 case '-': /* this will help the --help people */
150 case 'h':
151 usage++;
152 break;
153 case 'i':
154 indie++;
155 break; /* 8/28/91 TC */
156 case 'R':
157 if (getuid() == geteuid())
158 overload++;
159 break;
160 case 's':
161 xtrekPort = atoi(*argv);
162 callHost = 1;
163 argv++;
164 argc--;
165 break;
166 case 'M':
167 blk_metaserver = 1;
168 break;
169 case 'd':
170 host = *argv;
171 argc--;
172 argv++;
173 break;
174 /* netrek league stuff */
175 case 'O':
176 observer = 1;
177 break;
178 case 'H':
179 homeaway = HOME;
180 break;
181 case 'A':
182 homeaway = AWAY;
183 break;
184 default:
185 {
186 char buffer[100];
187 sprintf(buffer, "Unknown option '%c'\n", *ptr);
188 errorv[errorc++] = buffer;
189 break;
190 }
191 }
192 if (usage)
193 break;
194 ptr++;
195 }
196 }
197
198 if (usage || errorc)
199 {
200 int x;
201 char message[][255] = {
202 "\n\t'%s [options] -s <socket number> <display address>'\n\n",
203 "Options:\n",
204 "\t-h Help (this usage message)\n",
205 "\t-i Team independant\n",
206 "\t-R Reserved slot\n",
207 "\t-s Socket number\n",
208 "\t-M Metaserver\n",
209 "\t-d Display\n",
210 "\t-O Observer\n",
211 "\t-H Home (League Play)\n",
212 "\t-A Away (League Play)\n",
213 "\nNOTE: %s is designed to be launched by the startup process\n\n",
214 "\0"
215 };
216
217 fprintf(stderr, "-- NetrekII (Paradise), %s --\n", PARAVERS);
218 for (x = 0; x < errorc; x++)
219 fprintf(stderr, "\n%s: %s", argv0, errorv[x]);
220 for (x = 0; *message[x] != '\0'; x++)
221 fprintf(stderr, message[x], argv0);
222
223 exit(1);
224 }
225
226 openmem(1, homeaway != NEITHER);
227
228 /* compatability */
229 if (argc > 0)
230 host = argv[0];
231 srand48(getpid() + time((time_t *) 0));
232 /* this finds the shared memory information */
233
234 #if 0
235 if (blk_metaserver)
236 {
237 FILE *ptr;
238 char *buf;
239 buf = build_path("logs/metaserver.log");
240 ptr = fopen(buf, "a");
241 fprintf(ptr, "Connection from meta-server\n");
242 fclose(ptr);
243 }
244 #endif
245
246
247 me = NULL; /* UDP fix (?) */
248 if (callHost)
249 {
250 if (!connectToClient(host, xtrekPort))
251 {
252 exit(0);
253 }
254 }
255 else
256 {
257 sock = 0; /* Because we were forked by inetd! */
258 checkSocket();
259 initClientData(); /* "normally" called by connectToClient() */
260 }
261
262 starttime = time(NULL);
263 while (userVersion == 0)
264 {
265 /*
266 * Waiting for user to send his version number. We give him ten seconds
267 * to do so...
268 */
269 if (starttime + 10 < time(NULL))
270 {
271 exit(1);
272 }
273 socketPause();
274 readFromClient();
275 }
276 if (!checkVersion())
277 exit(1);
278
279 pno = findslot(overload, homeaway);
280 if (pno < 0)
281 {
282 /* print some appropriate message */
283 exit(1);
284 }
285
286 #if defined(sparc) && !defined(SVR4)
287 on_exit(atexitfunc, (caddr_t) 0);
288 #else
289 atexit(atexitfunc); /* register a function to execute at exit */
290 #endif
291
292 me = &players[pno];
293 me->p_no = pno;
294 me->p_team = NOBODY;
295 me->p_stats.st_royal = 0;
296 #ifdef RC_DISTRESS
297 me->gen_distress = 0; /* default to RCD off */
298 #endif
299 me->p_ntspid = getpid();
300 myship = &me->p_ship;
301 mystats = &me->p_stats;
302 lastm = mctl->mc_current;
303 me->p_lastrefit = -1;
304 me->p_spyable = 1;
305 me->p_teamspy = ~0;
306 #if 0
307 me->p_planfrac = 0; /* reset fractional parts */
308 me->p_bombfrac = 0; /* reset fractional parts */
309 #endif
310
311 /* --------------------------[ CLUECHECK stuff ]-------------------------- */
312 #ifdef CLUECHECK1
313 me->p_cluedelay = 10;
314 me->p_cluecountdown = 0;
315 #endif
316
317 #ifdef CLUECHECK2
318 me->p_cluedelay = lrand48() % 1000; /* so it doesn't ask them immediately */
319 me->p_cluecountdown = 0;
320 #endif
321 /* ----------------------------------------------------------------------- */
322
323 #ifndef AUTHORIZE
324 strcpy(RSA_client_type, "server doesn't support RSA");
325 #endif
326
327 (void) r_signal(SIGINT, SIG_IGN);
328 (void) r_signal(SIGCHLD, reaper);
329
330 /*
331 * We set these so we won't bother updating him on the location of the
332 * other players in the galaxy which he is not near. There is no real harm
333 * to doing this, except that he would then get more information than he
334 * deserves. It is kind of a hack, but should be harmless.
335 */
336 me->p_x = -100000;
337 me->p_y = -100000;
338 me->p_homeaway = homeaway;
339 me->p_observer = observer;
340
341 #if 0
342 updateGameparams();
343 #endif
344
345 updateSelf(); /* so he gets info on who he is */
346 updateShips(); /* put this back so maybe something will work */
347 /* with Andy's meta-server */
348
349 if (!blk_metaserver)
350 {
351 updateStatus();
352 updatePlanets();
353 updateTerrain();
354 }
355 #if 1
356 updateGameparams();
357 #endif
358
359 flushSockBuf();
360
361 /* Get login name */
362
363 #if 0
364 if ((pwent = getpwuid(getuid())) != NULL)
365 (void) strncpy(login, pwent->pw_name, sizeof(login));
366 else
367 #endif
368 (void) strncpy(login, "Bozo", sizeof(login));
369 login[sizeof(login) - 1] = '\0';
370
371 strcpy(pseudo, "Guest");
372
373 strcpy(me->p_name, pseudo);
374 me->p_team = ALLTEAM;
375 getname();
376 if (me->p_stats.st_rank >= NUMRANKS)
377 me->p_stats.st_rank = NUMRANKS - 1;
378 if (me->p_stats.st_royal >= NUMROYALRANKS)
379 me->p_stats.st_royal = NUMROYALRANKS - 1;
380 strcpy(pseudo, me->p_name);
381 strcpy(start_name, me->p_name); /* change 1/25/91 TC */
382
383 sendShipCap(); /* KAO 1/25/93 */
384
385 keeppeace = (me->p_stats.st_flags & ST_KEEPPEACE) == ST_KEEPPEACE;
386
387 /*
388 * Set p_hostile to hostile, so if keeppeace is on, the guy starts off
389 * hating everyone (like a good fighter should)
390 */
391 me->p_hostile = (FED | ROM | KLI | ORI);
392 s_type = CRUISER;
393 me->p_planets = 0;
394 me->p_armsbomb = 0;
395 me->p_dooshes = 0;
396 me->p_resbomb = 0;
397 /* Set up a reasonable default */
398 me->p_whydead = KQUIT;
399
400 (void) strncpy(me->p_login, login, sizeof(me->p_login));
401 me->p_login[sizeof(me->p_login) - 1] = '\0';
402 strcpy(start_login, login); /* change 1/25/91 TC */
403 {
404 int i;
405 for (i = 0; i < MAXPLAYER; i++)
406 ignored[i] = 0;
407 }
408
409 (void) strncpy(me->p_monitor, host, sizeof(me->p_monitor));
410 me->p_monitor[sizeof(me->p_monitor) - 1] = '\0';
411
412 /* assume this is only place p_monitor is set, and mirror accordingly */
413 /* 4/13/92 TC */
414 (void) strncpy(me->p_full_hostname, host, sizeof(me->p_full_hostname));
415 me->p_full_hostname[sizeof(me->p_full_hostname) - 1] = '\0';
416
417 logEntry(); /* moved down to get login/monitor 2/12/92
418 * TMC */
419
420 me->p_avrt = -1; /* ping stats */
421 me->p_stdv = -1;
422 me->p_pkls = -1;
423
424 startTkills = me->p_stats.st_tkills;
425 startTlosses = me->p_stats.st_tlosses;
426 startTarms = me->p_stats.st_tarmsbomb;
427 startTplanets = me->p_stats.st_tplanets;
428 startTticks = me->p_stats.st_tticks;
429
430 r_signal(SIGHUP, exitGame); /* allows use of HUP to force a clean exit */
431
432
433
434 me->p_status = POUTFIT;
435 repCount = 0;
436
437 while (1)
438 {
439 switch (me->p_status)
440 {
441 case POUTFIT:
442 case PTQUEUE:
443 /* give the player the motd and find out which team he wants */
444 if (me->p_status != PALIVE)
445 {
446 me->p_x = -100000;
447 me->p_y = -100000;
448 updateSelf();
449 updateShips();
450 teamPick = -1;
451 flushSockBuf();
452 getEntry(&team, &s_type);
453 }
454 if (goAway)
455 { /* change 4/14/91 TC */
456 printStats();
457 exit(0);
458 }
459 if (team == -1)
460 {
461 exitGame();
462 }
463
464 if (indie)
465 team = 4; /* force to independent 8/28/91 TC */
466 inputMask = -1; /* Allow all input now */
467 enter(team, 0, pno, s_type, -1);
468 /* for (i = 0; i < NSIG; i++) { r_signal(i, SIG_IGN); } */
469
470 me->p_status = me->p_observer ? POBSERVE : PALIVE; /* Put player in game */
471 me->p_ghostbuster = 0;
472 break;
473 case PALIVE:
474 case PEXPLODE:
475 case PDEAD:
476 case POBSERVE:
477 /* Get input until the player quits or dies */
478
479
480 input();
481 break;
482 default:
483 if (tmpPick != PATROL)
484 {
485 printf("player status = %d. exiting\n", me->p_status);
486 exitGame();
487 }
488 }
489 }
490
491 /* NOTREACHED */
492 return 1;
493 }
494
495 extern int setflag(); /* input.c */
496
497 int interrupting = 0;
498
499 void
500 stop_interruptor()
501 {
502 struct itimerval udt;
503
504 if (!interrupting)
505 return;
506
507 r_signal(SIGALRM, SIG_IGN); /* set up signals */
508 udt.it_interval.tv_sec = 0;
509 udt.it_interval.tv_usec = 0;
510 udt.it_value.tv_sec = 0;
511 udt.it_value.tv_usec = 0;
512 setitimer(ITIMER_REAL, &udt, 0);
513
514 interrupting = 0;
515 }
516
517 void
518 start_interruptor()
519 {
520 struct itimerval udt;
521
522 if (interrupting)
523 return;
524
525 {
526 int min_delay = me->p_observer
527 ? configvals->min_observer_upd_delay
528 : configvals->min_upd_delay;
529
530 if (timerDelay < min_delay)
531 timerDelay = min_delay;
532 }
533
534 r_signal(SIGALRM, SIG_IGN); /* set up signals */
535 udt.it_interval.tv_sec = 0;
536 udt.it_interval.tv_usec = timerDelay;
537 udt.it_value.tv_sec = 0;
538 udt.it_value.tv_usec = timerDelay;
539 setitimer(ITIMER_REAL, &udt, 0);
540
541 r_signal(SIGALRM, setflag);
542
543 interrupting = 1;
544 }
545
546 #if 0
547
548 /*
549 * this is TOTALLY untested. It probably doesn't belong in this file,
550 * either. When I figure out all the mechanisms, this will replace the while
551 * loop in main(). RF
552 */
553
554 void
555 inputloop()
556 {
557 static int switching = -1; /* is the player changing teams? */
558
559 int status = me->p_status;
560
561 while (1)
562 {
563 switch (status)
564 {
565 case PFREE:
566 status = me->p_status = PDEAD;
567 me->p_explode = 600;
568 stop_interruptor();
569 break;
570
571 case POUTFIT:
572 case PTQUEUE:
573 updateSelf();
574 updateShips();
575 sendMaskPacket(tournamentMask(me->p_team));
576 briefUpdateClient();
577 teamPick = -1;
578 socketPause();
579 break;
580
581 case PEXPLODE:
582 case PDEAD:
583 inputMask = 0;
584 case PALIVE:
585 socketWait();
586 delay_interrupt(); /* don't let client read be interrupted by
587 * the interval timer */
588 /*
589 * ^-- won't work.. delay_interrupt doesn't stop ALRMs from happening
590 * (HAK 9/21)
591 */
592 break;
593 }
594
595 /* me->p_status could change in here. */
596 readFromClient();
597
598 if (isClientDead())
599 {
600 if (!reconnect())
601 {
602 /* me->p_status=PFREE; should this be done? RF */
603 exit(0);
604 }
605 }
606 switch (status)
607 {
608 case POUTFIT:
609 case PTQUEUE:
610 if (teamPick == -1)
611 break;
612
613 if (teamPick < 0 || teamPick > 3 /* XXX */ )
614 {
615 warning("That is not a valid team.");
616 sendPickokPacket(0);
617 }
618 else if (!(tournamentMask(me->p_team) & (1 << teamPick)))
619 {
620 warning("I cannot allow that. Pick another team");
621 sendPickokPacket(0);
622 }
623 else if (((1 << teamPick) != me->p_team) &&
624 (me->p_team != ALLTEAM) &&
625 switching != teamPick &&
626 me->p_whydead != KGENOCIDE)
627 { /* switching teams */
628 switching = teamPick;
629 warning("Please confirm change of teams. Select the new team again.");
630 sendPickokPacket(0);
631 }
632 else if (shipPick < 0 || shipPick >= NUM_TYPES)
633 {
634 /* His team choice is ok. */
635 warning("That is an illegal ship type. Try again.");
636 sendPickokPacket(0);
637 }
638 else if (!allowed_ship(1 << teamPick, mystats->st_rank, mystats->st_royal, shipPick))
639 {
640 sendPickokPacket(0);
641 }
642 else
643 {
644
645 if (goAway)
646 { /* what does this do ? */
647 printStats();
648 exit(0);
649 }
650 if (indie)
651 me->p_team = 4;
652
653 inputMask = -1;
654
655 enter(teamPick, 0, me->p_no, shipPick, -1);
656
657 status = me->p_status = me->p_observer ? POBSERVER : PALIVE;
658 start_interruptor(); /* since we're alive, we need regular
659 * interrupts now */
660
661 me->p_ghostbuster = 0;
662
663 repCount = 0;
664
665 }
666 break;
667 case PALIVE:
668 case PEXPLODE:
669 case PDEAD:
670 if (0 /* sendflag */ )
671 { /* this is still busted, ugh */
672 check_authentication();
673 if (me->p_status == PFREE)
674 {
675 me->p_ghostbuster = 0;
676 me->p_status = PDEAD;
677 }
678 if ((me->p_status == PDEAD || me->p_status == POUTFIT)
679 && (me->p_ntorp <= 0)
680 && (me->p_nplasmatorp <= 0))
681 {
682 stop_interruptor();
683 death();
684 status = POUTFIT;
685 }
686 auto_features();
687 updateClient();
688
689 /* sendflag=0; ugh, broke */
690 }
691 reenable_interrupt();
692 }
693 }
694 }
695
696 #endif
697
698
699 void
700 exitGame()
701 {
702 char buf[80];
703 char addrbuf[20];
704
705 if (me != NULL && me->p_team != ALLTEAM)
706 {
707 sprintf(buf, "%s %s (%s) leaving game (%.16s@%.32s)",
708 ((me->p_stats.st_royal) ? royal[me->p_stats.st_royal].name
709 : ranks[me->p_stats.st_rank].name),
710 me->p_name,
711 twoletters(me),
712 me->p_login,
713 me->p_full_hostname
714 );
715 sprintf(addrbuf, " %s->ALL", twoletters(me));
716 pmessage2(buf, 0, MALL | MLEAVE, addrbuf, me->p_no);
717 me->p_stats.st_flags &= ~ST_CYBORG; /* clear this flag 8/27/91 TC */
718 savestats();
719 printStats();
720 }
721 me->p_status = PFREE;
722 move_player(me->p_no, -1, -1, 1);
723 exit(0);
724 }
725
726 #if defined(sparc) && !defined(SVR4)
727 int
728 atexitfunc(status, arg)
729 int status;
730 caddr_t arg;
731 #else
732 void
733 atexitfunc()
734 #endif
735 {
736 me->p_ntspid = 0;
737 me->p_status = PFREE;
738 }
739
740 #define PLURAL(n) (((n)==1)?"":"s")
741
742 static char *weapon_types[WP_MAX] = {
743 "Plasma torpedos",
744 "Tractors",
745 "Missiles",
746 "Fighters",
747 };
748
749 void
750 sendSysDefs()
751 {
752 char buf[200], buf2[200];
753 int i;
754
755 sendMotdLine("\t@@@");
756
757 if (!time_access())
758 {
759 sendMotdLine("** WE ARE CLOSED, CHECK HOURS **");
760 sendMotdLine("");
761 }
762
763 sendMotdLine("Available ship types:");
764 buf[0] = 0;
765 for (i = 0; i < NUM_TYPES; i++)
766 {
767 struct ship *s = &shipvals[i];
768 if (!shipsallowed[i])
769 continue;
770 sprintf(buf2, " %c) %s/%c%c", s->s_letter, s->s_name,
771 s->s_desig1, s->s_desig2);
772 if (strlen(buf) + strlen(buf2) > 80)
773 {
774 sendMotdLine(buf);
775 strcpy(buf, buf2);
776 }
777 else
778 {
779 strcat(buf, buf2);
780 }
781 }
782 /* guaranteed to have stuff here */
783 sendMotdLine(buf);
784 sendMotdLine("");
785 sendMotdLine(
786 "SHIP REQUIRED RANK BUILD TIME LIMIT NUM PLYRS NUM PLNTS");
787
788 for (i = 0; i < NUM_TYPES; i++)
789 {
790 struct ship *s = &shipvals[i];
791 if (!shipsallowed[i])
792 continue;
793 buf2[0] = 0;
794 if (s->s_rank > 0 || s->s_timer > 0 || s->s_maxnum < 16 ||
795 s->s_numdefn || s->s_numplan)
796 {
797 sprintf(buf2, "%-13s%-16s", s->s_name,
798 s->s_rank ? ranks[s->s_rank].name : "none");
799 if (s->s_timer > 0)
800 sprintf(buf, "%d minutes", s->s_timer);
801 else
802 strcpy(buf, "none");
803 sprintf(buf2 + strlen(buf2), "%-14s", buf);
804
805 if (s->s_maxnum < 16)
806 sprintf(buf, "%d/team", s->s_maxnum);
807 else
808 strcpy(buf, "none");
809 sprintf(buf2 + strlen(buf2), "%-12s %-3d %-3d", buf,
810 s->s_numdefn, s->s_numplan);
811 sendMotdLine(buf2);
812 }
813 }
814 sendMotdLine("");
815
816
817 buf2[0] = 0;
818 for (i = 0; i < WP_MAX; i++)
819 {
820 if (weaponsallowed[i])
821 {
822 if (buf2[0])
823 strcat(buf2, ", ");
824 strcat(buf2, weapon_types[i]);
825 }
826 }
827 sprintf(buf, "Special weapons enabled: %s", buf2[0] ? buf2 : "none");
828 sendMotdLine(buf);
829
830 if (weaponsallowed[WP_PLASMA])
831 {
832 sprintf(buf, "You need %.1f kill%s to get plasma torpedos",
833 configvals->plkills, PLURAL(configvals->plkills));
834 sendMotdLine(buf);
835 }
836 if (weaponsallowed[WP_MISSILE])
837 {
838 sprintf(buf, "You need %.1f kill%s to get missiles",
839 configvals->mskills, PLURAL(configvals->mskills));
840 sendMotdLine(buf);
841 }
842 sendMotdLine("");
843
844 sprintf(buf, "Tournament mode requires %d player%s per team",
845 configvals->tournplayers, PLURAL(configvals->tournplayers));
846 sendMotdLine(buf);
847 /* sendMotdLine(""); */
848
849 /* We don't blab about newturn */
850 #if 0
851 sendMotdLine(configvals->hiddenenemy ?
852 "Visibility is restricted during T-mode" :
853 "Visibility is unlimited all the time");
854 #endif
855 sendMotdLine(configvals->binconfirm ?
856 "Only authorized binaries are allowed" :
857 "Non-authorized binaries are detected but not rejected");
858
859 if (configvals->planetlimittype)
860 {
861 sprintf(buf, "Independent planets may be taken if your team has fewer than %d planets", configvals->planetsinplay);
862 sendMotdLine(buf);
863 }
864 else
865 {
866 sprintf(buf, "Only %d planets can be in play at once",
867 configvals->planetsinplay);
868 sendMotdLine(buf);
869 }
870
871 if (configvals->planupdspd == 0)
872 {
873 sendMotdLine("Planets do not orbit their stars");
874 }
875 else
876 {
877 sprintf(buf, "Planets orbit their stars at a rate of %g",
878 configvals->planupdspd);
879 sendMotdLine(buf);
880 }
881 sendMotdLine(configvals->warpdecel ?
882 "New warp deceleration code is in effect" :
883 "Old-style instant warp deceleration is in effect");
884 sprintf(buf, "The next galaxy will be generated using method #%d",
885 configvals->galaxygenerator);
886 sendMotdLine(buf);
887 sendMotdLine
888 (configvals->affect_shiptimers_outside_T ?
889 "Ship deaths outside tournament mode affect construction timers" :
890 "Construction timers are not affected by ship deaths outside tournament mode");
891
892 sprintf(buf, "Cloaking during warp prep is %sallowed",
893 configvals->cloakduringwarpprep ? "" : "not ");
894 sendMotdLine(buf);
895
896 sprintf(buf, "Cloaking during warp is %sallowed",
897 configvals->cloakwhilewarping ? "" : "not ");
898 sendMotdLine(buf);
899
900 sprintf(buf, "Variable warp speed is %sabled",
901 configvals->variable_warp ? "en" : "dis");
902 sendMotdLine(buf);
903
904 sprintf(buf, "Warp prep suspension is %sallowed",
905 configvals->warpprep_suspendable ? "" : "not ");
906 sendMotdLine(buf);
907
908 switch (configvals->warpprepstyle)
909 {
910 case WPS_NOTRACT:
911 sendMotdLine("Tractors do not affect warp prep");
912 break;
913 case WPS_TABORT:
914 sendMotdLine("Tractors make warp fail to engage");
915 break;
916 case WPS_TPREVENT:
917 sendMotdLine("Tractors prevent entering warp");
918 break;
919 case WPS_TABORTNOW:
920 sendMotdLine("Tractors abort warp prep countdown");
921 break;
922 case WPS_TSUSPEND:
923 sendMotdLine("Tractors suspend warp prep countdown");
924 break;
925 }
926
927 sprintf(buf, "There is a %d%% chance that you'll orbit a planet CCW",
928 (int) ((1.0 - configvals->orbitdirprob) * 100));
929 sendMotdLine(buf);
930
931 sprintf(buf, "Army growth: %d. Pop choice: %d. Pop speed: %d%%.",
932 configvals->popscheme, configvals->popchoice, configvals->popspeed);
933 sendMotdLine(buf);
934
935 if (configvals->warpzone)
936 {
937 sprintf(buf, "Warp zones are enabled with radius %d.",
938 configvals->warpzone);
939 }
940 else
941 {
942 sprintf(buf, "Warp zones are disabled.");
943 }
944 sendMotdLine(buf);
945 }
946
947 void
948 sendMotd()
949 {
950 FILE *motd;
951 char buf[100], buf2[30]; /* big enough... */
952 char *paths;
953
954 time_t curtime;
955 struct tm *tmstruct;
956 int hour, tacc;
957
958 time(&curtime);
959 tmstruct = localtime(&curtime);
960 if (!(hour = tmstruct->tm_hour % 12))
961 hour = 12;
962 sprintf(buf, "Netrek II (Paradise) server %s, connection established at %d:%02d%s.",
963 PARAVERS,
964 hour,
965 tmstruct->tm_min,
966 tmstruct->tm_hour >= 12 ? "pm" : "am");
967
968 /*
969 * if (!(tacc = time_access())) strcat(buf, " WE'RE CLOSED, CHECK HOURS");
970 */
971 sendMotdLine(buf);
972 sendMotdLine(" ");
973
974 if (!blk_flag)
975 {
976 paths = build_path(WCMOTD); /* Wrong client message */
977 if ((motd = fopen(paths, "r")) != NULL)
978 {
979 while (fgets(buf, sizeof(buf), motd) != NULL)
980 {
981 buf[strlen(buf) - 1] = '\0';
982 sendMotdLine(buf);
983 }
984 fclose(motd);
985 }
986 else
987 { /* default message */
988 sendMotdLine(" ");
989 sendMotdLine(
990 " ****************************************************************");
991 sendMotdLine(" ");
992
993 sendMotdLine(
994 " This is a Paradise server; you need a Paradise client to play!");
995 sendMotdLine(" ");
996 sendMotdLine(
997 " Paradise clients can be had from");
998 sendMotdLine(
999 " ftp.cis.ufl.edu pub/netrek.paradise/");
1000 sendMotdLine(
1001 " ftp.reed.edu mirrors/netrek.paradise/");
1002 sendMotdLine(" ");
1003 sendMotdLine(
1004 " ****************************************************************");
1005 }
1006 return;
1007 }
1008
1009 /* if (blk_flag) */
1010 { /* added 1/19/93 KAO */
1011 int i, first = 1;
1012
1013 strcpy(buf, "BLK: REFIT ");
1014
1015 for (i = 0; i < NUM_TYPES; i++)
1016 {
1017 struct ship *s = &shipvals[i];
1018 if (!shipsallowed[i])
1019 continue;
1020
1021 if (!first)
1022 strcat(buf, ", ");
1023 else
1024 first = 0;
1025
1026 sprintf(buf2, "%c) %c%c", s->s_letter, s->s_desig1, s->s_desig2);
1027 strcat(buf, buf2);
1028 }
1029 sendMotdLine(buf);
1030 }
1031 /* the following will read a motd */
1032 if (!time_access())
1033 {
1034 paths = build_path(CLOSEDMOTD);
1035 if ((motd = fopen(paths, "r")) == NULL)
1036 {
1037 paths = build_path(MOTD);
1038 motd = fopen(paths, "r");
1039 }
1040 }
1041 else
1042 {
1043 paths = build_path(MOTD);
1044 motd = fopen(paths, "r");
1045 }
1046 if (motd != NULL)
1047 {
1048 #ifdef CLUECHECK1
1049 init_motdbuf(paths);
1050 #endif
1051 while (fgets(buf, sizeof(buf), motd) != NULL)
1052 {
1053 buf[strlen(buf) - 1] = '\0';
1054 sendMotdLine(buf);
1055 }
1056 (void) fclose(motd);
1057 }
1058 sendSysDefs();
1059
1060 /* wait till the end for the pictures */
1061 if (!blk_metaserver)
1062 doMotdPics();
1063 }
1064
1065 int
1066 reaper(sig)
1067 int sig;
1068 {
1069 #ifndef SVR4
1070 while (wait3((union wait *) 0, WNOHANG, (struct rusage *) 0) > 0);
1071 #else
1072 while (waitpid(0, NULL, WNOHANG) > 0);
1073 #endif /* SVR4 */
1074 return 0;
1075 }
1076
1077 void
1078 printStats()
1079 {
1080 FILE *logfile;
1081 #if defined(SVR4) || defined(sparc)
1082 time_t curtime;
1083 #else
1084 int curtime;
1085 #endif /* SVR4 */
1086 char *paths; /* added 1/18/93 KAO */
1087
1088 paths = build_path(LOGFILENAME);
1089 logfile = fopen(paths, "a");
1090 if (!logfile)
1091 return;
1092 curtime = time(NULL);
1093
1094 #ifdef LOG_LONG_INFO /*-[ Long info printed to logfiles and startup.log ]-*/
1095 fprintf(logfile, "Leaving: %-16s (%s) %3dP %3dA %3dW/%3dL %3dmin %drtt %dsdv %dls %dplan <%s@%s> %s",
1096 me->p_name,
1097 twoletters(me),
1098 me->p_stats.st_tplanets - startTplanets,
1099 me->p_stats.st_tarmsbomb - startTarms,
1100 me->p_stats.st_tkills - startTkills,
1101 me->p_stats.st_tlosses - startTlosses,
1102 (me->p_stats.st_tticks - startTticks) / 600,
1103 me->p_avrt, me->p_stdv, me->p_pkls,
1104 numPlanets(me->p_team),
1105
1106 #else
1107
1108 fprintf(logfile, "Leaving: %s <%s@%s> %s",
1109 me->p_name,
1110 #endif
1111 me->p_login,
1112 me->p_full_hostname,
1113 ctime(&curtime));
1114
1115 /* #endif /*-[ LOG_LONG_INFO ]- */
1116
1117 if (goAway)
1118 fprintf(logfile, "^^^ 2 players/1 slot. was %s (%s)\n",
1119 start_name, start_login);
1120 fclose(logfile);
1121 }
1122
1123
1124 /*
1125 * .pics file format:
1126 *
1127 * name x y page name x y page etc
1128 */
1129
1130 void
1131 doMotdPics()
1132 {
1133 FILE *ptr, *ftemp;
1134 char buf[128], fname[128];
1135 unsigned char *bits;
1136 char *result;
1137 int x, y, page, w, h;
1138 int bytesperline; /* pad the width to a byte */
1139 int linesperblock; /* how many lines in 1016 bytes? */
1140 int i;
1141 char *paths;
1142
1143 paths = build_path(PICS);
1144 ptr = fopen(paths, "r");
1145 if (ptr == NULL)
1146 return;
1147 while (1)
1148 {
1149 result = fgets(fname, 125, ptr);
1150 if (result == NULL)
1151 /* must fclose ptr */
1152 break;
1153
1154 if (fname[strlen(fname) - 1] == '\n')
1155 fname[strlen(fname) - 1] = 0;
1156
1157 paths = build_path(fname);
1158 ftemp = fopen(paths, "r");
1159 bits = 0;
1160 if (ftemp == 0)
1161 {
1162 fprintf(stderr, "ntserv: couldn't open file %s. skipping\n", paths);
1163 }
1164 else
1165 {
1166 ParseXbmFile(ftemp, &w, &h, &bits); /* parsexbm.c */
1167
1168 bytesperline = (w - 1) / 8 + 1;
1169 linesperblock = 1016 /* packets.h */ / bytesperline;
1170 }
1171
1172 fgets(buf, 125, ptr);
1173
1174 if (3 != sscanf(buf, "%d %d %d", &x, &y, &page))
1175 {
1176 printf("Format error in .pics file\n");
1177 if (bits)
1178 free(bits);
1179 bits = NULL;
1180 }
1181
1182 if (bits)
1183 {
1184 if (me != 0 && (me->p_stats.st_flags & ST_NOBITMAPS))
1185 {
1186 sendMotdNopic(x, y, page, w, h);
1187 }
1188 else
1189 for (i = 0; i * linesperblock < h; i++)
1190 {
1191 int nlines;
1192 if ((i + 1) * linesperblock > h)
1193 nlines = h - i * linesperblock;
1194 else
1195 nlines = linesperblock;
1196 #if 0
1197 printf("Sending MotdPics: %s %d %d %d %d %d\n",
1198 fname, x, y + i * linesperblock, page, w, nlines);
1199 #endif
1200 sendMotdPic(x, y + i * linesperblock,
1201 bits + bytesperline * linesperblock * i,
1202 page, w, nlines);
1203 }
1204 free(bits);
1205 }
1206 }
1207 fclose(ptr);
1208 }
1209
1210
1211 #undef D