Mercurial > ~darius > hgwebdir.cgi > paradise_server
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 |