4
|
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
|