home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / games / volume17 / gbp / part03 < prev    next >
Encoding:
Text File  |  1993-03-20  |  54.4 KB  |  2,019 lines

  1. Path: uunet!news.tek.com!master!saab!billr
  2. From: billr@saab.CNA.TEK.COM (Bill Randle)
  3. Newsgroups: comp.sources.games
  4. Subject: v17i015:  gbp - Galactic Bloodshed+, an empire-like war game, Part03/21
  5. Message-ID: <4543@master.CNA.TEK.COM>
  6. Date: 12 Feb 93 17:29:59 GMT
  7. Sender: news@master.CNA.TEK.COM
  8. Lines: 2007
  9. Approved: billr@saab.CNA.TEK.COM
  10. Xref: uunet comp.sources.games:1694
  11.  
  12. Submitted-by: deragon@harpo.cs.nyu.edu (Seeker)
  13. Posting-number: Volume 17, Issue 15
  14. Archive-name: gbp/Part03
  15. Supersedes: gb3: Volume 10, Issue 1-14
  16. Environment: sockets, curses
  17.  
  18.  
  19.  
  20. #! /bin/sh
  21. # This is a shell archive.  Remove anything before this line, then unpack
  22. # it by saving it into a file and typing "sh file".  To overwrite existing
  23. # files, type "sh file -c".  You can also feed this as standard input via
  24. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  25. # will see the following message at the end:
  26. #        "End of archive 3 (of 21)."
  27. # Contents:  server/GB_server.c server/access.c
  28. # Wrapped by billr@saab on Fri Feb 12 09:14:24 1993
  29. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  30. if test -f 'server/GB_server.c' -a "${1}" != "-c" ; then 
  31.   echo shar: Will not clobber existing file \"'server/GB_server.c'\"
  32. else
  33. echo shar: Extracting \"'server/GB_server.c'\" \(48398 characters\)
  34. sed "s/^X//" >'server/GB_server.c' <<'END_OF_FILE'
  35. X/*
  36. X * Galactic Bloodshed, copyright (c) 1989 1990 by Robert P. Chansky,
  37. X * smq@ucscb.ucsc.edu, Univ of Ca Santa Cruz. You may copy, alter and
  38. X * distribute this game as you please as long as these notices remain intact.
  39. X * No duplication for commercial purposes without permission of the author.
  40. X * 
  41. X * Version 1.0 - current mods by: Garrett Van Cleef, Ph.D Dept. of Physics Ohio
  42. X * State University V1.1 playtesting by: Hanan Baddar Ken Bloch John Davis
  43. X * Robert Jones Menelaos Kafkaladis Brett Lowry Paul Murphy Garrett van Cleef
  44. X * Wolfgang Wenzel and tons of people at U.C. Santa Cruz
  45. X * 
  46. X * 
  47. X * Major amounts of help in v2.0-current by Brian Scearce (bls@u02.svl.cdc.com).
  48. X */
  49. X
  50. X/*
  51. X * Fri Dec 11 01:59:53 EST 1992 
  52. X *
  53. X * Started major rework of code.  See the file doc/CHANGES for information.
  54. X *
  55. X * Work on GB is now for the most part solely conducted by the GBDT which
  56. X * consists of:
  57. X *
  58. X * John Paul Deragon (deragon@jethro.nyu.edu)  
  59. X * Chris Fodor       (cfodor@ucsd.edu)
  60. X * Evan Koffleva     (koffleva@darkwing.uoregon.edu)
  61. X * Roger Lewis       (rlewis@isi.edu)
  62. X * Jonathan Roy      (ninja@halcyon.com)
  63. X *
  64. X */
  65. X
  66. X#include "TinyMUD_copyright.h"
  67. X/*
  68. X * Copyright for the original TinyMUD interface which was used for the
  69. X * networking
  70. X */
  71. X#include <stdio.h>
  72. X#include <sys/types.h>
  73. X#include <sys/file.h>
  74. X#include <sys/time.h>
  75. X#include <signal.h>
  76. X#include <sys/ioctl.h>
  77. X#include <sys/wait.h>
  78. X#include <sys/stat.h>
  79. X#include <fcntl.h>
  80. X#include <sys/errno.h>
  81. X#include <ctype.h>
  82. X#include <sys/socket.h>
  83. X#include <netinet/in.h>
  84. X#include <netdb.h>
  85. X#include <csp.h>
  86. X
  87. X#include <curses.h>
  88. X#include <strings.h>
  89. X#include <pwd.h>
  90. X
  91. X#include <sys/uio.h>
  92. X#include <sys/timeb.h>
  93. X
  94. X/* GB headers */
  95. X#define EXTERN
  96. X#include "vars.h"
  97. X#include "ships.h"
  98. X#include "races.h"
  99. X#include "power.h"
  100. X#include "doturn.h"
  101. X
  102. X#include "interface.h"
  103. X#include "buffers.h"
  104. X
  105. X/* datafile descriptors */
  106. Xint             commoddata, pdata, racedata, sectdata, shdata, stdata;
  107. X
  108. Xstruct descriptor_data *descriptor_list;
  109. Xextern long     Shipdata[NUMSTYPES][NUMABILS];
  110. Xextern int      errno;
  111. Xtime_t            clk;
  112. Xint             shutdown_flag = 0;
  113. Xint             update_flag = 0;
  114. X
  115. Xint             port;        /* port selection */
  116. Xstruct tm      *current_tm;    /* for watching for next update */
  117. Xchar            start_buf[128];
  118. Xchar            update_buf[128];
  119. Xchar            segment_buf[128];
  120. X
  121. Xstatic char    *flushed_message = "<Output Flushed>\n";
  122. Xstatic char    *shutdown_message = "Shutdown ordered by deity - Bye\n";
  123. X/*
  124. X * DO NOT change these two lines.... they are client specific
  125. X * and are used in the login procedure according to the CLIENT
  126. X * PROTOCOL file
  127. X * -- JPD --
  128. X */
  129. Xstatic char    *client_login = "Enter Password <race> <gov>:\n";
  130. Xstatic char    *client_invalid = "Invalid: ";
  131. Xstatic char    *already_on = "Player already logged on!\n";
  132. Xstatic char    *bad_password = "Bad Password.\n";
  133. X
  134. Xint             errno;
  135. Xint             sig_null();
  136. X
  137. X
  138. Xstatic int      sock;
  139. Xstatic int      ndescriptors = 0;
  140. X
  141. Xvoid            set_signals(void);
  142. Xvoid            notify_race(int, char *);
  143. Xint             notify(int, int, char *);
  144. Xvoid            d_think(int, int, char *);
  145. Xvoid            d_broadcast(int, int, char *, int);
  146. Xvoid            d_shout(int, int, char *);
  147. Xvoid            d_announce(int, int, int, char *);
  148. Xstruct timeval  timeval(struct timeval, struct timeval);
  149. Xint             msec_diff(struct timeval, struct timeval);
  150. Xstruct timeval  msec_add(struct timeval, int);
  151. Xvoid            shovechars(int);
  152. Xvoid            do_next_thing(void);
  153. Xvoid            shutdownsock(struct descriptor_data *);
  154. Xint             make_socket(int);
  155. Xstruct timeval  update_quotas(struct timeval, struct timeval);
  156. Xstruct descriptor_data *new_connection(int);
  157. Xchar           *addrout(long);
  158. Xvoid            clearstrings(struct descriptor_data *);
  159. Xvoid            shutdown_sock(struct descriptor_data *);
  160. Xstruct descriptor_data *initializesock(int);
  161. Xstruct text_block *make_text_block(char *, int);
  162. Xvoid            free_text_block(struct text_block *);
  163. Xvoid            add_to_queue(struct text_queue *, char *, int);
  164. Xint             flush_queue(struct text_queue *, int);
  165. Xvoid            queue_write(struct descriptor_data *, char *, int);
  166. Xvoid            queue_string(struct descriptor_data * d, char *message);
  167. Xint             process_output(struct descriptor_data *);
  168. Xint             process_string(struct descriptor_data *);
  169. Xvoid            force_output(void);
  170. Xvoid            make_nonblocking(int);
  171. Xvoid            freeqs(struct descriptor_data *);
  172. Xvoid            welcome_user(struct descriptor_data *);
  173. Xvoid            goodbye_user(struct descriptor_data *);
  174. Xchar           *strsave(char *);
  175. Xvoid            save_command(struct descriptor_data *, char *);
  176. Xint             process_input(struct descriptor_data *);
  177. Xvoid            set_userstring(char **, char *);
  178. Xvoid            process_commands(void);
  179. Xint             do_command(struct descriptor_data *, char *);
  180. Xvoid            check_connect(struct descriptor_data *, char *);
  181. Xvoid            do_update(int);
  182. Xvoid            do_segment(int, int);
  183. Xvoid            parse_connect(char *, char *, char *);
  184. Xvoid            close_sockets(void);
  185. Xvoid            dump_users(struct descriptor_data *);
  186. Xvoid            process_command(int, int, char *);
  187. Xvoid            GB_time(int, int);
  188. Xvoid            kill_ship(int, shiptype *);
  189. Xvoid            compute_power_blocks(void);
  190. Xvoid            insert_sh_univ(struct stardata *, shiptype *);
  191. Xvoid            insert_sh_star(startype *, shiptype *);
  192. Xvoid            insert_sh_plan(planettype *, shiptype *);
  193. Xvoid            insert_sh_ship(shiptype *, shiptype *);
  194. Xvoid            remove_sh_star(shiptype *);
  195. Xvoid            remove_sh_plan(shiptype *);
  196. Xvoid            remove_sh_ship(shiptype *, shiptype *);
  197. Xdouble          GetComplexity(int);
  198. Xint             ShipCompare(int *, int *);
  199. Xvoid            SortShips(void);
  200. Xvoid            warn_race(int, char *);
  201. Xvoid            warn(int, int, char *);
  202. Xvoid            warn_star(int, int, int, char *);
  203. Xvoid            notify_star(int, int, int, int, char *);
  204. Xvoid            post_star(char *, int, int);
  205. Xint                send_special_string(int, int);
  206. X
  207. X#include "proto.h"
  208. X
  209. X#ifdef DEBUG
  210. Xvoid            DEBUG_check(int, int);
  211. Xvoid            DEBUG_reset(int, int);
  212. X#endif
  213. X
  214. Xchar           *Desnames[] = {
  215. X    "ocean", "land", "mountainous", "gaseous", "ice", "forest", "desert",
  216. X"plated", "wasted"};
  217. X
  218. Xchar            Dessymbols[] = {
  219. X    CHAR_SEA, CHAR_LAND, CHAR_MOUNT, CHAR_GAS, CHAR_ICE, CHAR_FOREST,
  220. XCHAR_DESERT, CHAR_PLATED, CHAR_WASTED};
  221. X
  222. X
  223. Xvoid
  224. Xmain(int argc, char **argv)
  225. X{
  226. X    int             i;
  227. X    struct stat     stbuf;
  228. X    FILE           *sfile;
  229. X
  230. X
  231. X    clearlog(TRUE);
  232. X    loginfo(ERRORLOG, NOERRNO, "GB server started");
  233. X
  234. X    open_data_files();
  235. X    clk = time(0);
  236. X    switch (argc) {
  237. X    case 2:
  238. X        port = atoi(argv[1]);
  239. X        update_time = DEFAULT_UPDATE_TIME;
  240. X        segments = MOVES_PER_UPDATE;
  241. X        break;
  242. X    case 3:
  243. X        port = atoi(argv[1]);
  244. X        update_time = atoi(argv[2]);
  245. X        segments = MOVES_PER_UPDATE;
  246. X        break;
  247. X    case 4:
  248. X        port = atoi(argv[1]);
  249. X        update_time = atoi(argv[2]);
  250. X        segments = atoi(argv[3]);
  251. X        break;
  252. X    default:
  253. X        port = GB_PORT;
  254. X        update_time = DEFAULT_UPDATE_TIME;
  255. X        segments = MOVES_PER_UPDATE;
  256. X        break;
  257. X    }
  258. X    loginfo(ERRORLOG, NOERRNO, "Running on Port %d\n", port);
  259. X    loginfo(UPDATELOG, NOERRNO, "%d minutes between updates", update_time);
  260. X    loginfo(UPDATELOG, NOERRNO, "%d segments/update", segments);
  261. X
  262. X    next_update_time = clk + (update_time * 60);
  263. X    if (stat(UPDATEFL, &stbuf) >= 0) {
  264. X        if (sfile = fopen(UPDATEFL, "r")) {
  265. X            char            dum[32];
  266. X            if (fgets(dum, sizeof dum, sfile))
  267. X                nupdates_done = atoi(dum);
  268. X            if (fgets(dum, sizeof dum, sfile))
  269. X                last_update_time = atol(dum);
  270. X            if (fgets(dum, sizeof dum, sfile))
  271. X                next_update_time = atol(dum);
  272. X            fclose(sfile);
  273. X        }
  274. X        loginfo(UPDATELOG, NOERRNO, "Last update %3d : %s", nupdates_done,
  275. X            ctime(&last_update_time));
  276. X    }
  277. X    if (segments <= 1)
  278. X        next_segment_time += (144 * 3600);
  279. X    else {
  280. X        next_segment_time = clk + (update_time * 60 / segments);
  281. X        if (stat(SEGMENTFL, &stbuf) >= 0) {
  282. X            if (sfile = fopen(SEGMENTFL, "r")) {
  283. X                char            dum[32];
  284. X                if (fgets(dum, sizeof dum, sfile))
  285. X                    nsegments_done = atoi(dum);
  286. X                if (fgets(dum, sizeof dum, sfile))
  287. X                    last_segment_time = atol(dum);
  288. X                if (fgets(dum, sizeof dum, sfile))
  289. X                    next_segment_time = atol(dum);
  290. X                fclose(sfile);
  291. X            }
  292. X        }
  293. X        if (next_segment_time < clk) {    /* gvc */
  294. X            next_segment_time = next_update_time;
  295. X            nsegments_done = segments;
  296. X        }
  297. X    }
  298. X    loginfo(UPDATELOG, NOERRNO, "Last Segment %2d : %s", nsegments_done,
  299. X        ctime(&last_segment_time));
  300. X
  301. X    loginfo(UPDATELOG, NOERRNO, "Next Update %d : %s",
  302. X        nupdates_done + 1, ctime(&next_update_time));
  303. X    loginfo(UPDATELOG, NOERRNO, "Next Segment   : %s", ctime(&next_segment_time));
  304. X
  305. X    srandom(getpid());
  306. X
  307. X
  308. X    load_race_data();    /* make sure you do this first */
  309. X    load_star_data();    /* get star data */
  310. X    Getpower(Power);    /* get power report from disk */
  311. X    Getblock(Blocks);    /* get alliance block data */
  312. X    SortShips();        /* Sort the ship list by tech for "build ?" */
  313. X    for (i = 1; i <= MAXPLAYERS; i++) {
  314. X        setbit(Blocks[i - 1].invite, i);
  315. X        setbit(Blocks[i - 1].pledge, i);
  316. X    }
  317. X    Putblock(Blocks);
  318. X    compute_power_blocks();
  319. X    set_signals();
  320. X    shovechars(port);
  321. X    close_sockets();
  322. X    close_data_files();
  323. X    loginfo(ERRORLOG, NOERRNO, "Going down.");
  324. X    exit(1);
  325. X}
  326. X
  327. Xvoid 
  328. Xset_signals(void)
  329. X{
  330. X    signal(SIGPIPE, SIG_IGN);
  331. X}
  332. X
  333. Xvoid 
  334. Xnotify_race(int race, char *message)
  335. X{
  336. X    struct descriptor_data *d;
  337. X    if (update_flag)
  338. X        return;
  339. X    for (d = descriptor_list; d; d = d->next) {
  340. X        if (d->connected && d->Playernum == race) {
  341. X            queue_string(d, message);
  342. X        }
  343. X    }
  344. X}
  345. X
  346. Xint 
  347. Xsend_special_string(int player, int what)
  348. X{
  349. X    struct descriptor_data *d;
  350. X    char                   message[24];
  351. X
  352. X    for (d = descriptor_list; d; d = d->next)
  353. X      if (d->connected && d->Playernum == player &&
  354. X        races[d->Playernum -1]->governor[d->Governor].CSP_client_info.csp_user)         {
  355. X            switch (what) {
  356. X                case UPDATE_START:
  357. X                    sprintf(message, "%c %d\n", CSP_CLIENT, CSP_UPDATE_START);
  358. X                        break;
  359. X                case UPDATE_END:
  360. X                    sprintf(message, "%c %d %d\n", CSP_CLIENT, CSP_UPDATE_END,
  361. X                        nupdates_done);
  362. X                    break;
  363. X                case SEGMENT_START:
  364. X                    sprintf(message, "%c %d\n", CSP_CLIENT, CSP_SEGMENT_START);
  365. X                    break;
  366. X                case SEGMENT_END:
  367. X                    sprintf(message, "%c %d\n", CSP_CLIENT, CSP_SEGMENT_END);
  368. X                    break;
  369. X                case RESET_START:
  370. X                    sprintf(message, "%c %d\n", CSP_CLIENT, CSP_RESET_START);
  371. X                    break;
  372. X                case RESET_END:
  373. X                    sprintf(message, "%c %d\n", CSP_CLIENT, CSP_RESET_END);
  374. X                    break;
  375. X            }
  376. X            queue_string(d, message);
  377. X            return(1);
  378. X        }
  379. X    return(0);
  380. X}
  381. X
  382. Xint 
  383. Xnotify(int race, int gov, char *message)
  384. X{
  385. X    struct descriptor_data *d;
  386. X    reg int         ok;
  387. X
  388. X    if (update_flag)
  389. X        return 0;
  390. X    ok = 0;
  391. X    for (d = descriptor_list; d; d = d->next)
  392. X        if (d->connected && d->Playernum == race && d->Governor == gov) {
  393. X            queue_string(d, message);
  394. X            ok = 1;
  395. X        }
  396. X    return ok;
  397. X}
  398. X
  399. Xvoid 
  400. Xd_think(int Playernum, int Governor, char *message)
  401. X{
  402. X    struct descriptor_data *d;
  403. X    for (d = descriptor_list; d; d = d->next) {
  404. X        if (d->connected && d->Playernum == Playernum && d->Governor != Governor &&
  405. X        !races[d->Playernum - 1]->governor[d->Governor].toggle.gag) {
  406. X            queue_string(d, message);
  407. X        }
  408. X    }
  409. X}
  410. X
  411. Xvoid 
  412. Xd_broadcast(int Playernum, int Governor, char *message, int channel_wanted)
  413. X{
  414. X    struct descriptor_data *d;
  415. X    for (d = descriptor_list; d; d = d->next) {
  416. X#ifdef MULTIPLE_COMM_CHANNELS
  417. X        if (d->connected && !(d->Playernum == Playernum && d->Governor == Governor) &&
  418. X        !races[d->Playernum - 1]->governor[d->Governor].toggle.gag && 
  419. X        isset(races[d->Playernum -1]->governor[d->Governor].channel, 
  420. X            channel_wanted)) {
  421. X#else
  422. X        if (d->connected && !(d->Playernum == Playernum && d->Governor == Governor) &&
  423. X        !races[d->Playernum - 1]->governor[d->Governor].toggle.gag) {
  424. X#endif
  425. X            queue_string(d, message);
  426. X        }
  427. X    }
  428. X}
  429. X
  430. Xvoid 
  431. Xd_shout(int Playernum, int Governor, char *message)
  432. X{
  433. X    struct descriptor_data *d;
  434. X    for (d = descriptor_list; d; d = d->next) {
  435. X        if (d->connected && !(d->Playernum == Playernum && d->Governor == Governor)) {
  436. X            queue_string(d, message);
  437. X        }
  438. X    }
  439. X}
  440. X
  441. Xvoid 
  442. Xd_announce(int Playernum, int Governor, int star, char *message)
  443. X{
  444. X    struct descriptor_data *d;
  445. X    for (d = descriptor_list; d; d = d->next) {
  446. X        if (d->connected && !(d->Playernum == Playernum && d->Governor == Governor) &&
  447. X            (isset(Stars[star]->inhabited, d->Playernum) ||
  448. X             races[d->Playernum - 1]->God) &&
  449. X            Dir[d->Playernum - 1][d->Governor].snum == star &&
  450. X        !races[d->Playernum - 1]->governor[d->Governor].toggle.gag) {
  451. X            queue_string(d, message);
  452. X        }
  453. X    }
  454. X}
  455. X
  456. Xstruct timeval 
  457. Xtimeval_sub(struct timeval now, struct timeval then)
  458. X{
  459. X    now.tv_sec -= then.tv_sec;
  460. X    now.tv_usec -= then.tv_usec;
  461. X    if (now.tv_usec < 0) {
  462. X        now.tv_usec += 1000000;
  463. X        now.tv_sec--;
  464. X    }
  465. X    return now;
  466. X}
  467. X
  468. Xint 
  469. Xmsec_diff(struct timeval now, struct timeval then)
  470. X{
  471. X    return ((now.tv_sec - then.tv_sec) * 1000
  472. X        + (now.tv_usec - then.tv_usec) / 1000);
  473. X}
  474. X
  475. Xstruct timeval 
  476. Xmsec_add(struct timeval t, int x)
  477. X{
  478. X    t.tv_sec += x / 1000;
  479. X    t.tv_usec += (x % 1000) * 1000;
  480. X    if (t.tv_usec >= 1000000) {
  481. X        t.tv_sec += t.tv_usec / 1000000;
  482. X        t.tv_usec = t.tv_usec % 1000000;
  483. X    }
  484. X    return t;
  485. X}
  486. X
  487. Xvoid 
  488. Xshovechars(int port)
  489. X{
  490. X    fd_set          input_set, output_set;
  491. X    time_t          now, go_time;
  492. X    struct timeval  last_slice, current_time;
  493. X    struct timeval  next_slice;
  494. X    struct timeval  timeout, slice_timeout;
  495. X    int             maxd, i;
  496. X    struct descriptor_data *d, *dnext;
  497. X    struct descriptor_data *newd;
  498. X    int             avail_descriptors;
  499. X
  500. X    go_time = 0;
  501. X    sock = make_socket(port);
  502. X    maxd = sock + 1;
  503. X    gettimeofday(&last_slice, (struct timezone *) 0);
  504. X
  505. X    avail_descriptors = getdtablesize() - 4;
  506. X
  507. X    if (!shutdown_flag)
  508. X        post("Server started\n", ANNOUNCE);
  509. X    for (i = 0; i <= ANNOUNCE; i++)
  510. X        newslength[i] = Newslength(i);
  511. X
  512. X    while (!shutdown_flag) {
  513. X        fflush(stdout);
  514. X        gettimeofday(¤t_time, (struct timezone *) 0);
  515. X        last_slice = update_quotas(last_slice, current_time);
  516. X
  517. X        process_commands();
  518. X
  519. X        if (shutdown_flag)
  520. X            break;
  521. X        timeout.tv_sec = 30;
  522. X        timeout.tv_usec = 0;
  523. X        next_slice = msec_add(last_slice, COMMAND_TIME_MSEC);
  524. X        slice_timeout = timeval_sub(next_slice, current_time);
  525. X
  526. X        FD_ZERO(&input_set);
  527. X        FD_ZERO(&output_set);
  528. X        if (ndescriptors < avail_descriptors)
  529. X            FD_SET(sock, &input_set);
  530. X        for (d = descriptor_list; d; d = d->next) {
  531. X            if (d->input.head)
  532. X                timeout = slice_timeout;
  533. X            else
  534. X                FD_SET(d->descriptor, &input_set);
  535. X            if (d->output.head)
  536. X                FD_SET(d->descriptor, &output_set);
  537. X        }
  538. X
  539. X        if (select(maxd, &input_set, &output_set,
  540. X               (fd_set *) 0, &timeout) < 0) {
  541. X            if (errno != EINTR) {
  542. X                perror("select");
  543. X                return;
  544. X            }
  545. X            (void) time(&now);
  546. X        } else {
  547. X
  548. X            (void) time(&now);
  549. X
  550. X            if (FD_ISSET(sock, &input_set)) {
  551. X                if (!(newd = new_connection(sock))) {
  552. X                    if (errno && errno != EINTR && errno != EMFILE) {
  553. X                        perror("new_connection");
  554. X                        return;
  555. X                    }
  556. X                } else {
  557. X                    if (newd->descriptor >= maxd)
  558. X                        maxd = newd->descriptor + 1;
  559. X                }
  560. X            }
  561. X            for (d = descriptor_list; d; d = dnext) {
  562. X                dnext = d->next;
  563. X                if (FD_ISSET(d->descriptor, &input_set)) {
  564. X                    /* d->last_time = now; */
  565. X                    if (!process_input(d)) {
  566. X                        shutdownsock(d);
  567. X                        continue;
  568. X                    }
  569. X                }
  570. X                if (FD_ISSET(d->descriptor, &output_set)) {
  571. X                    if (!process_output(d)) {
  572. X                        shutdownsock(d);
  573. X                    }
  574. X                }
  575. X            }
  576. X
  577. X        }
  578. X        if (go_time == 0) {
  579. X            if (now >= next_update_time) {
  580. X                go_time = now + (int_rand(0, DEFAULT_RANDOM_UPDATE_RANGE) * 60);
  581. X            }
  582. X            if (now >= next_segment_time && nsegments_done < segments) {
  583. X                go_time = now + (int_rand(0, DEFAULT_RANDOM_SEGMENT_RANGE) * 60);
  584. X            }
  585. X        }
  586. X        if (go_time > 0 && now >= go_time) {
  587. X            (void) do_next_thing();
  588. X            go_time = 0;
  589. X        }
  590. X    }
  591. X}
  592. X
  593. Xvoid 
  594. Xdo_next_thing(void)
  595. X{
  596. X    clk = time(0);
  597. X    if (nsegments_done < segments)
  598. X        do_segment(0, 1);
  599. X    else
  600. X        do_update(0);
  601. X}
  602. X
  603. Xint 
  604. Xmake_socket(int port)
  605. X{
  606. X    int             s;
  607. X    struct sockaddr_in server;
  608. X    int             opt;
  609. X
  610. X    s = socket(AF_INET, SOCK_STREAM, 0);
  611. X    if (s < 0) {
  612. X        perror("creating stream socket");
  613. X        exit(3);
  614. X    }
  615. X    opt = 1;
  616. X    if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
  617. X               (char *) &opt, sizeof(opt)) < 0) {
  618. X        perror("setsockopt");
  619. X        exit(1);
  620. X    }
  621. X    if (setsockopt(s, SOL_SOCKET, SO_KEEPALIVE,    /* GVC */
  622. X               (char *) &opt, sizeof(opt)) < 0) {
  623. X        perror("setsockopt");
  624. X        exit(1);
  625. X    }
  626. X    server.sin_family = AF_INET;
  627. X    server.sin_addr.s_addr = INADDR_ANY;
  628. X    server.sin_port = htons(port);
  629. X    if (bind(s, (struct sockaddr *) & server, sizeof(server))) {
  630. X        perror("binding stream socket");
  631. X        close(s);
  632. X        exit(4);
  633. X    }
  634. X    listen(s, 5);
  635. X    return s;
  636. X}
  637. X
  638. Xstruct timeval 
  639. Xupdate_quotas(struct timeval last, struct timeval current)
  640. X{
  641. X    int             nslices;
  642. X    struct descriptor_data *d;
  643. X
  644. X    nslices = msec_diff(current, last) / COMMAND_TIME_MSEC;
  645. X
  646. X    if (nslices > 0) {
  647. X        for (d = descriptor_list; d; d = d->next) {
  648. X            d->quota += COMMANDS_PER_TIME * nslices;
  649. X            if (d->quota > COMMAND_BURST_SIZE)
  650. X                d->quota = COMMAND_BURST_SIZE;
  651. X        }
  652. X    }
  653. X    return msec_add(last, nslices * COMMAND_TIME_MSEC);
  654. X}
  655. X
  656. Xstruct descriptor_data *
  657. Xnew_connection(int sock)
  658. X{
  659. X    int             newsock;
  660. X    struct sockaddr_in addr;
  661. X    int             addr_len;
  662. X
  663. X    addr_len = sizeof(addr);
  664. X    newsock = accept(sock, (struct sockaddr *) & addr, &addr_len);
  665. X    if (newsock <= 0) {
  666. X        return 0;
  667. X    } else {
  668. X#ifdef ACCESS_CHECK
  669. X        if (address_ok(&addr)) {
  670. X            loginfo(USERLOG, NOERRNO, "ACCEPT from %s(%d) on descriptor %d\n",
  671. X                addrout(ntohl(addr.sin_addr.s_addr)),
  672. X                ntohs(addr.sin_port), newsock);
  673. X            return initializesock(newsock);
  674. X        } else {
  675. X            write(newsock, "Unauthorized Access.\n", 21);
  676. X            loginfo(USERLOG, NOERRNO, "REJECT from %s(%d) on descriptor %d\n",
  677. X                addrout(ntohl(addr.sin_addr.s_addr)),
  678. X                ntohs(addr.sin_port),
  679. X                newsock);
  680. X            shutdown(newsock, 2);
  681. X            close(newsock);
  682. X            errno = 0;
  683. X            return 0;
  684. X        }
  685. X#else
  686. X        loginfo(USERLOG, NOERRNO, "ACCEPT from %s(%d) on descriptor %d\n",
  687. X            addrout(ntohl(addr.sin_addr.s_addr)),
  688. X            ntohs(addr.sin_port), newsock);
  689. X        return initializesock(newsock);
  690. X#endif
  691. X    }
  692. X}
  693. X
  694. Xchar           *
  695. Xaddrout(long a)
  696. X{
  697. X    static char     outbuf[1024];
  698. X
  699. X    sprintf(outbuf, "%d.%d.%d.%d", (a >> 24) & 0xff, (a >> 16) & 0xff,
  700. X        (a >> 8) & 0xff, a & 0xff);
  701. X    return outbuf;
  702. X}
  703. X
  704. Xvoid 
  705. Xclearstrings(struct descriptor_data * d)
  706. X{
  707. X    if (d->output_prefix) {
  708. X        free(d->output_prefix);
  709. X        d->output_prefix = 0;
  710. X    }
  711. X    if (d->output_suffix) {
  712. X        free(d->output_suffix);
  713. X        d->output_suffix = 0;
  714. X    }
  715. X}
  716. X
  717. Xvoid 
  718. Xshutdownsock(struct descriptor_data * d)
  719. X{
  720. X    racetype *r;
  721. X
  722. X
  723. X    if (d->connected) {
  724. X        r = races[d->Playernum -1];
  725. X        loginfo(USERLOG, NOERRNO, "DISCONNECT: %d Race=%d Governor=%d",
  726. X            d->descriptor, d->Playernum, d->Governor);
  727. X        sprintf(buf, "\n%s \"%s\" [%d,%d] logged off.\n", r->name,
  728. X            r->governor[d->Governor].name, d->Playernum, d->Governor);
  729. X        notify_race(d->Playernum, buf);
  730. X    } else {
  731. X        loginfo(USERLOG, NOERRNO, "DISCONNECT: %d Never Connected.",
  732. X            d->descriptor);
  733. X    }
  734. X    clearstrings(d);
  735. X    shutdown(d->descriptor, 2);
  736. X    close(d->descriptor);
  737. X    freeqs(d);
  738. X    *d->prev = d->next;
  739. X    if (d->next)
  740. X        d->next->prev = d->prev;
  741. X    free(d);
  742. X    ndescriptors--;
  743. X}
  744. X
  745. Xstruct descriptor_data *
  746. Xinitializesock(int s)
  747. X{
  748. X    struct descriptor_data *d;
  749. X
  750. X    ndescriptors++;
  751. X    d = (struct descriptor_data *) malloc(sizeof(struct descriptor_data));
  752. X    d->descriptor = s;
  753. X    d->connected = 0;
  754. X    make_nonblocking(s);
  755. X    d->output_prefix = 0;
  756. X    d->output_suffix = 0;
  757. X    d->output_size = 0;
  758. X    d->output.head = 0;
  759. X    d->output.tail = &d->output.head;
  760. X    d->input.head = 0;
  761. X    d->input.tail = &d->input.head;
  762. X    d->raw_input = 0;
  763. X    d->raw_input_at = 0;
  764. X    d->quota = COMMAND_BURST_SIZE;
  765. X    d->last_time = 0;
  766. X    if (descriptor_list)
  767. X        descriptor_list->prev = &d->next;
  768. X    d->next = descriptor_list;
  769. X    d->prev = &descriptor_list;
  770. X    descriptor_list = d;
  771. X
  772. X    welcome_user(d);
  773. X    queue_string(d, client_login);
  774. X    return d;
  775. X}
  776. X
  777. Xstruct text_block *
  778. Xmake_text_block(char *s, int n)
  779. X{
  780. X    struct text_block *p;
  781. X
  782. X    p = (struct text_block *) malloc(sizeof(struct text_block));
  783. X    p->buf = (char *) malloc(n * sizeof(char));
  784. X    bcopy(s, p->buf, n);
  785. X    p->nchars = n;
  786. X    p->start = p->buf;
  787. X    p->nxt = 0;
  788. X    return p;
  789. X}
  790. X
  791. Xvoid 
  792. Xfree_text_block(struct text_block * t)
  793. X{
  794. X    free(t->buf);
  795. X    free((char *) t);
  796. X}
  797. X
  798. Xvoid 
  799. Xadd_to_queue(struct text_queue * q, char *b, int n)
  800. X{
  801. X    struct text_block *p;
  802. X
  803. X    if (n == 0)
  804. X        return;
  805. X
  806. X    p = make_text_block(b, n);
  807. X    p->nxt = 0;
  808. X    *q->tail = p;
  809. X    q->tail = &p->nxt;
  810. X}
  811. X
  812. Xint 
  813. Xflush_queue(struct text_queue * q, int n)
  814. X{
  815. X    struct text_block *p;
  816. X    int             really_flushed = 0;
  817. X
  818. X    n += strlen(flushed_message);
  819. X
  820. X    while (n > 0 && (p = q->head)) {
  821. X        n -= p->nchars;
  822. X        really_flushed += p->nchars;
  823. X        q->head = p->nxt;
  824. X        free_text_block(p);
  825. X    }
  826. X    p = make_text_block(flushed_message, strlen(flushed_message));
  827. X    p->nxt = q->head;
  828. X    q->head = p;
  829. X    if (!p->nxt)
  830. X        q->tail = &p->nxt;
  831. X    really_flushed -= p->nchars;
  832. X    return really_flushed;
  833. X}
  834. X
  835. Xvoid 
  836. Xqueue_write(struct descriptor_data * d, char *b, int n)
  837. X{
  838. X    int             space;
  839. X
  840. X    space = MAX_OUTPUT - d->output_size - n;
  841. X    if (space < 0)
  842. X        d->output_size -= flush_queue(&d->output, -space);
  843. X    add_to_queue(&d->output, b, n);
  844. X    d->output_size += n;
  845. X}
  846. X
  847. Xvoid 
  848. Xqueue_string(struct descriptor_data * d, char *s)
  849. X{
  850. X    queue_write(d, s, strlen(s));
  851. X}
  852. X
  853. Xint 
  854. Xprocess_output(struct descriptor_data * d)
  855. X{
  856. X    struct text_block **qp, *cur;
  857. X    int             cnt;
  858. X
  859. X    for (qp = &d->output.head; cur = *qp;) {
  860. X        cnt = write(d->descriptor, cur->start, cur->nchars);
  861. X        if (cnt < 0) {
  862. X            if (errno == EWOULDBLOCK)
  863. X                return 1;
  864. X            d->connected = 0;    /* added this */
  865. X            return 0;
  866. X        }
  867. X        d->output_size -= cnt;
  868. X        if (cnt == cur->nchars) {
  869. X            if (!cur->nxt)
  870. X                d->output.tail = qp;
  871. X            *qp = cur->nxt;
  872. X            free_text_block(cur);
  873. X            continue;    /* do not adv ptr */
  874. X        }
  875. X        cur->nchars -= cnt;
  876. X        cur->start += cnt;
  877. X        break;
  878. X    }
  879. X    return 1;
  880. X}
  881. X
  882. Xvoid 
  883. Xforce_output(void)
  884. X{
  885. X    struct descriptor_data *d;
  886. X
  887. X    for (d = descriptor_list; d; d = d->next)
  888. X        if (d->connected)
  889. X            (void) process_output(d);
  890. X}
  891. X
  892. Xvoid 
  893. Xmake_nonblocking(int s)
  894. X{
  895. X    if (fcntl(s, F_SETFL, FNDELAY) == -1) {
  896. X        perror("make_nonblocking: fcntl");
  897. X        exit(0);
  898. X    }
  899. X}
  900. X
  901. Xvoid 
  902. Xfreeqs(struct descriptor_data * d)
  903. X{
  904. X    struct text_block *cur, *next;
  905. X
  906. X    cur = d->output.head;
  907. X    while (cur) {
  908. X        next = cur->nxt;
  909. X        free_text_block(cur);
  910. X        cur = next;
  911. X    }
  912. X    d->output.head = 0;
  913. X    d->output.tail = &d->output.head;
  914. X
  915. X    cur = d->input.head;
  916. X    while (cur) {
  917. X        next = cur->nxt;
  918. X        free_text_block(cur);
  919. X        cur = next;
  920. X    }
  921. X    d->input.head = 0;
  922. X    d->input.tail = &d->input.head;
  923. X
  924. X    if (d->raw_input)
  925. X        free(d->raw_input);
  926. X    d->raw_input = 0;
  927. X    d->raw_input_at = 0;
  928. X}
  929. X
  930. Xvoid 
  931. Xgoodbye_user(struct descriptor_data * d)
  932. X{
  933. X    if (d->connected)    /* this can happen, especially after updates */
  934. X        write(d->descriptor, LEAVE_MESSAGE, strlen(LEAVE_MESSAGE));
  935. X}
  936. X
  937. Xchar           *
  938. Xstrsave(char *s)
  939. X{
  940. X    char           *p;
  941. X
  942. X    p = (char *) malloc((strlen(s) + 1) * sizeof(char));
  943. X
  944. X    if (p)
  945. X        strcpy(p, s);
  946. X    return p;
  947. X}
  948. X
  949. Xvoid 
  950. Xsave_command(struct descriptor_data * d, char *command)
  951. X{
  952. X    add_to_queue(&d->input, command, strlen(command) + 1);
  953. X}
  954. X
  955. Xint 
  956. Xprocess_input(struct descriptor_data * d)
  957. X{
  958. X    int             got;
  959. X    char           *p, *pend, *q, *qend;
  960. X
  961. X    got = read(d->descriptor, buf, sizeof buf);
  962. X    if (got <= 0)
  963. X        return 0;
  964. X    if (!d->raw_input) {
  965. X        d->raw_input = (char *) malloc(MAX_COMMAND_LEN * sizeof(char));
  966. X        d->raw_input_at = d->raw_input;
  967. X    }
  968. X    p = d->raw_input_at;
  969. X    pend = d->raw_input + MAX_COMMAND_LEN - 1;
  970. X    for (q = buf, qend = buf + got; q < qend; q++) {
  971. X        if (*q == '\n') {
  972. X            *p = '\0';
  973. X            if (p > d->raw_input)
  974. X                save_command(d, d->raw_input);
  975. X            p = d->raw_input;
  976. X        } else if (p < pend && isascii(*q) && isprint(*q)) {
  977. X            *p++ = *q;
  978. X        }
  979. X    }
  980. X    if (p > d->raw_input) {
  981. X        d->raw_input_at = p;
  982. X    } else {
  983. X        free(d->raw_input);
  984. X        d->raw_input = 0;
  985. X        d->raw_input_at = 0;
  986. X    }
  987. X    return 1;
  988. X}
  989. X
  990. Xvoid 
  991. Xset_userstring(char **userstring, char *comm)
  992. X{
  993. X    if (*userstring) {
  994. X        free(*userstring);
  995. X        *userstring = 0;
  996. X    }
  997. X    while (*comm && isascii(*comm) && isspace(*comm))
  998. X        comm++;
  999. X    if (*comm)
  1000. X        *userstring = strsave(comm);
  1001. X}
  1002. X
  1003. Xvoid 
  1004. Xprocess_commands(void)
  1005. X{
  1006. X    int             nprocessed;
  1007. X    long            now;
  1008. X    struct descriptor_data *d, *dnext;
  1009. X    struct text_block *t;
  1010. X
  1011. X
  1012. X    (void) time(&now);
  1013. X
  1014. X    do {
  1015. X        nprocessed = 0;
  1016. X        for (d = descriptor_list; d; d = dnext) {
  1017. X            dnext = d->next;
  1018. X            if (d->quota > 0 && (t = d->input.head)) {
  1019. X                d->quota--;
  1020. X                nprocessed++;
  1021. X
  1022. X                if (!do_command(d, t->start)) {
  1023. X                    shutdownsock(d);
  1024. X                } else {
  1025. X                    d->last_time = now;    /* experimental code */
  1026. X                    d->input.head = t->nxt;
  1027. X                    if (!d->input.head)
  1028. X                        d->input.tail = &d->input.head;
  1029. X                    free_text_block(t);
  1030. X                    d->last_time = now;    /* experimental code */
  1031. X                }
  1032. X
  1033. X            }
  1034. X        }
  1035. X    } while (nprocessed > 0);
  1036. X
  1037. X}
  1038. X
  1039. Xint 
  1040. Xdo_command(struct descriptor_data * d, char *comm)
  1041. X{
  1042. X    char           *string;
  1043. X    int             parse_exit = 0, i;
  1044. X
  1045. X    argn = 0;
  1046. X    /*
  1047. X     * Main processing loop. When command strings are sent from the
  1048. X     * client, they are processed here. Responses are sent back to the
  1049. X     * client via notify. The client will then process the strings in
  1050. X     * whatever manner is expected.
  1051. X     */
  1052. X
  1053. X    /*
  1054. X     * check to see if there are a few words typed out, usually for the
  1055. X     * help command
  1056. X     */
  1057. X    string = comm;
  1058. X    while (!parse_exit) {
  1059. X        i = 0;
  1060. X        while (!isspace(*string) && (*string != '\0') && (i < COMMANDSIZE))
  1061. X            args[argn][i++] = (*string++);
  1062. X        args[argn][i] = '\0';
  1063. X        while ((*string) == ' ')
  1064. X            string++;
  1065. X        if ((*string == '\0') || (argn >= MAXARGS))
  1066. X            parse_exit = 1;
  1067. X        argn++;
  1068. X    }
  1069. X    for (i = argn; i < MAXARGS; i++)
  1070. X        args[i][0] = '\0';
  1071. X
  1072. X    if (!strcmp(args[0], QUIT_COMMAND)) {
  1073. X        goodbye_user(d);
  1074. X        return 0;
  1075. X    } else if (d->connected && !strcmp(args[0], WHO_COMMAND)) {
  1076. X        dump_users(d);
  1077. X    } else if (!strcmp(args[0], HELP_COMMAND)) {
  1078. X        help(d);
  1079. X    } else if (d->connected && d->God && !strcmp(args[0], EMULATE_COMMAND)) {
  1080. X        d->Playernum = atoi(args[1]);
  1081. X        d->Governor = atoi(args[2]);
  1082. X        sprintf(buf, "Emulating %s \"%s\" [%d,%d]\n", races[d->Playernum - 1]->name,
  1083. X            races[d->Playernum - 1]->governor[d->Governor].name,
  1084. X            d->Playernum, d->Governor);
  1085. X        queue_string(d, buf);
  1086. X    } else {
  1087. X        if (d->connected) {
  1088. X            /* GB command parser */
  1089. X            process_command(d->Playernum, d->Governor, comm);
  1090. X        } else {
  1091. X            check_connect(d, comm);    /* Logs player into the game,
  1092. X                         * connects if the password
  1093. X                         * given by *command is a
  1094. X                         * player's */
  1095. X            if (!d->connected) {
  1096. X                goodbye_user(d);
  1097. X            } else {
  1098. X                check_for_telegrams(d->Playernum, d->Governor);
  1099. X                /* set the scope to home upon login */
  1100. X                argn = 1;
  1101. X                strcpy(args[0], "cs");
  1102. X                process_command(d->Playernum, d->Governor, "cs");
  1103. X            }
  1104. X        }
  1105. X    }
  1106. X    return 1;
  1107. X}
  1108. X
  1109. Xvoid 
  1110. Xcheck_connect(struct descriptor_data * d, char *message)
  1111. X{
  1112. X    char            race_password[MAX_COMMAND_LEN];
  1113. X    char            gov_password[MAX_COMMAND_LEN];
  1114. X    int             i, j;
  1115. X    int             Playernum, Governor;
  1116. X    racetype       *r;
  1117. X    struct descriptor_data *d0, *dnext;
  1118. X
  1119. X
  1120. X    parse_connect(message, race_password, gov_password);
  1121. X
  1122. X#ifdef EXTERNAL_TRIGGER
  1123. X    if (!strcmp(password, SEGMENT_PASSWORD)) {
  1124. X        do_segment(1, 0);
  1125. X        return;
  1126. X    } else if (!strcmp(password, UPDATE_PASSWORD)) {
  1127. X        do_update(1);
  1128. X        return;
  1129. X    }
  1130. X#endif
  1131. X
  1132. X    Getracenum(race_password, gov_password, &i, &j);
  1133. X
  1134. X    if (!i) {
  1135. X        sprintf(buf, "%s %s\n", client_invalid, bad_password);
  1136. X        queue_string(d, buf);
  1137. X        loginfo(USERLOG, NOERRNO, "FAILED CONNECT: %s,%s on descriptor %d",
  1138. X            race_password, gov_password, d->descriptor);
  1139. X        queue_string(d, client_login);
  1140. X    } else {
  1141. X        Playernum = i;
  1142. X        Governor = j;
  1143. X        r = races[i - 1];
  1144. X        /*
  1145. X         * check to see if this player is already connect, if so,
  1146. X         * nuke the descriptor
  1147. X         */
  1148. X        for (d0 = descriptor_list; d0; d0 = dnext) {
  1149. X            dnext = d0->next;
  1150. X            if (d0->connected && d0->Playernum == Playernum &&
  1151. X                d0->Governor == Governor) {
  1152. X                sprintf(buf, "%s %s\n", client_invalid, already_on);
  1153. X                queue_string(d, buf);
  1154. X                queue_string(d, client_login);
  1155. X                return;
  1156. X            }
  1157. X        }
  1158. X
  1159. X        loginfo(USERLOG, NOERRNO, "CONNECTED: %s \"%s\" [%d,%d] on descriptor %d",
  1160. X            r->name, r->governor[j].name, Playernum, Governor, d->descriptor);
  1161. X        d->connected = 1;
  1162. X
  1163. X        d->God = r->God;
  1164. X        d->Playernum = Playernum;
  1165. X        d->Governor = Governor;
  1166. X
  1167. X        sprintf(buf, "\n%s \"%s\" [%d,%d] logged on.\n", r->name,
  1168. X            r->governor[j].name, Playernum, Governor);
  1169. X        notify_race(Playernum, buf);
  1170. X        sprintf(buf, "You are %s.\n",
  1171. X         r->governor[j].toggle.invisible ? "invisible" : "visible");
  1172. X        notify(Playernum, Governor, buf);
  1173. X
  1174. X        GB_time(Playernum, Governor);
  1175. X        sprintf(buf, "\nLast login      : %s", ctime(&(r->governor[j].login)));
  1176. X        notify(Playernum, Governor, buf);
  1177. X        r->governor[j].login = time(0);
  1178. X#ifdef MULTIPLE_COMM_CHANNELS
  1179. X        setbit(races[Playernum -1]->governor[Governor].channel,
  1180. X            COMM_CHANNEL1);
  1181. X        setbit(races[Playernum -1]->governor[Governor].channel, 
  1182. X            COMM_DEF_CHANNEL1);
  1183. X        clrbit(races[Playernum -1]->governor[Governor].channel, 
  1184. X            COMM_DEF_CHANNEL2);
  1185. X        clrbit(races[Playernum -1]->governor[Governor].channel, 
  1186. X            COMM_DEF_CHANNEL3);
  1187. X#endif 
  1188. X        putrace(r);
  1189. X        if (!r->Gov_ship) {
  1190. X            strcat(buf, "You have no Governmental Center.  No action points will be produced\nuntil you build one and designate a capital.\n");
  1191. X            notify(Playernum, Governor, buf);
  1192. X        } else {
  1193. X            sprintf(buf, "Government Center #%d is active.\n", r->Gov_ship);
  1194. X            notify(Playernum, Governor, buf);
  1195. X        }
  1196. X        sprintf(buf, "     Morale: %d\n", r->morale);
  1197. X        notify(Playernum, Governor, buf);
  1198. X        treasury(Playernum, Governor);
  1199. X    }
  1200. X}
  1201. X
  1202. Xvoid 
  1203. Xdo_update(int override)
  1204. X{
  1205. X    register int    i;
  1206. X    FILE           *sfile;
  1207. X    struct stat     stbuf;
  1208. X    int             fakeit;
  1209. X    int                client;
  1210. X    
  1211. X    fakeit = (!override && stat(NOGOFL, &stbuf) >= 0);
  1212. X
  1213. X    sprintf(buf, "%sDOING UPDATE...\n", ctime(&clk));
  1214. X    if (!fakeit) {
  1215. X        for (i = 1; i <= Num_races; i++)  
  1216. X            if (!send_special_string(i, UPDATE_START))
  1217. X                notify_race(i, buf);
  1218. X        force_output();
  1219. X    }
  1220. X    if (segments <= 1) {
  1221. X        /* Disables movement segments. */
  1222. X        next_segment_time = clk + (144 * 3600);
  1223. X        nsegments_done = segments;
  1224. X    } else {
  1225. X        if (override)
  1226. X            next_segment_time = clk + update_time * 60 / segments;
  1227. X        else
  1228. X            next_segment_time = next_update_time + update_time * 60 / segments;
  1229. X        nsegments_done = 1;
  1230. X    }
  1231. X    if (override)
  1232. X        next_update_time = clk + update_time * 60;
  1233. X    else
  1234. X        next_update_time += update_time * 60;
  1235. X
  1236. X    if (!fakeit)
  1237. X        nupdates_done++;
  1238. X
  1239. X    sprintf(Power_blocks.time, "%s", ctime(&clk));
  1240. X    sprintf(update_buf, "Last Update %3d : %s", nupdates_done, ctime(&clk));
  1241. X    sprintf(segment_buf, "Last Segment %2d : %s", nsegments_done, ctime(&clk));
  1242. X
  1243. X    loginfo(UPDATELOG, NOERRNO, "Next Update %3d : %s",
  1244. X        nupdates_done + 1, ctime(&next_update_time));
  1245. X    loginfo(UPDATELOG, NOERRNO, "Next Segment %2d : %s",
  1246. X        nsegments_done == segments ? 1 : nsegments_done + 1,
  1247. X        ctime(&next_segment_time));
  1248. X
  1249. X    unlink(UPDATEFL);
  1250. X    if (sfile = fopen(UPDATEFL, "w")) {
  1251. X        fprintf(sfile, "%d\n", nupdates_done);
  1252. X        fprintf(sfile, "%ld\n", clk);
  1253. X        fprintf(sfile, "%ld\n", next_update_time);
  1254. X        fflush(sfile);
  1255. X        fclose(sfile);
  1256. X    }
  1257. X    unlink(SEGMENTFL);
  1258. X    if (sfile = fopen(SEGMENTFL, "w")) {
  1259. X        fprintf(sfile, "%d\n", nsegments_done);
  1260. X        fprintf(sfile, "%ld\n", clk);
  1261. X        fprintf(sfile, "%ld\n", next_segment_time);
  1262. X        fflush(sfile);
  1263. X        fclose(sfile);
  1264. X    }
  1265. X    update_flag = 1;
  1266. X    if (!fakeit)
  1267. X        do_turn(1);
  1268. X    update_flag = 0;
  1269. X    clk = time(0);
  1270. X    sprintf(buf, "%sUpdate %d finished\n", ctime(&clk), nupdates_done);
  1271. X    if (!fakeit) {
  1272. X        for (i = 1; i <= Num_races; i++)
  1273. X            if (!send_special_string(i, UPDATE_END))
  1274. X                notify_race(i, buf);
  1275. X        force_output();
  1276. X    }
  1277. X}
  1278. X
  1279. Xvoid 
  1280. Xdo_segment(int override, int segment)
  1281. X{
  1282. X    register int    i;
  1283. X    FILE           *sfile;
  1284. X    struct stat     stbuf;
  1285. X    int             fakeit;
  1286. X
  1287. X    fakeit = (!override && stat(NOGOFL, &stbuf) >= 0);
  1288. X
  1289. X    if (!override && segments <= 1)
  1290. X        return;
  1291. X
  1292. X    sprintf(buf, "%sDOING MOVEMENT...\n", ctime(&clk));
  1293. X    if (!fakeit) {
  1294. X        for (i = 1; i <= Num_races; i++)
  1295. X            if (!send_special_string(i, SEGMENT_START))
  1296. X                notify_race(i, buf);
  1297. X        force_output();
  1298. X    }
  1299. X    if (override) {
  1300. X        next_segment_time = clk + update_time * 60 / segments;
  1301. X        if (segment) {
  1302. X            nsegments_done = segment;
  1303. X            next_update_time = clk + update_time * 60 *
  1304. X                (segments - segment + 1) / segments;
  1305. X        } else {
  1306. X            nsegments_done++;
  1307. X        }
  1308. X    } else {
  1309. X        next_segment_time += update_time * 60 / segments;
  1310. X        nsegments_done++;
  1311. X    }
  1312. X
  1313. X    update_flag = 1;
  1314. X    if (!fakeit)
  1315. X        do_turn(0);
  1316. X    update_flag = 0;
  1317. X    unlink(SEGMENTFL);
  1318. X    if (sfile = fopen(SEGMENTFL, "w")) {
  1319. X        fprintf(sfile, "%d\n", nsegments_done);
  1320. X        fprintf(sfile, "%ld\n", clk);
  1321. X        fprintf(sfile, "%ld\n", next_segment_time);
  1322. X        fflush(sfile);
  1323. X        fclose(sfile);
  1324. X    }
  1325. X    sprintf(segment_buf, "Last Segment %2d : %s",
  1326. X        nsegments_done, ctime(&clk));
  1327. X    loginfo(UPDATELOG, NOERRNO, "Next Segment %2d : %s",
  1328. X        nsegments_done, ctime(&next_segment_time));
  1329. X    clk = time(0);
  1330. X    sprintf(buf, "%sSegment finished\n", ctime(&clk));
  1331. X    if (!fakeit) {
  1332. X        for (i = 1; i <= Num_races; i++)
  1333. X            if (!send_special_string(i, SEGMENT_END))
  1334. X                notify_race(i, buf);
  1335. X        force_output();
  1336. X    }
  1337. X}
  1338. X
  1339. Xvoid 
  1340. Xparse_connect(char *message, char *race_pass, char *gov_pass)
  1341. X{
  1342. X    char           *p;
  1343. X    char           *q;
  1344. X    /* race password */
  1345. X    while (*message && isascii(*message) && isspace(*message))
  1346. X        message++;
  1347. X    p = race_pass;
  1348. X    while (*message && isascii(*message) && !isspace(*message))
  1349. X        *p++ = *message++;
  1350. X    *p = '\0';
  1351. X    /* governor password */
  1352. X    while (*message && isascii(*message) && isspace(*message))
  1353. X        message++;
  1354. X    q = gov_pass;
  1355. X    while (*message && isascii(*message) && !isspace(*message))
  1356. X        *q++ = *message++;
  1357. X    *q = '\0';
  1358. X}
  1359. X
  1360. Xvoid 
  1361. Xclose_sockets(void)
  1362. X{
  1363. X    struct descriptor_data *d, *dnext;
  1364. X    /* post message into news file */
  1365. X    post(shutdown_message, ANNOUNCE);
  1366. X
  1367. X    for (d = descriptor_list; d; d = dnext) {
  1368. X        dnext = d->next;
  1369. X        write(d->descriptor, shutdown_message, strlen(shutdown_message));
  1370. X        if (shutdown(d->descriptor, 2) < 0)
  1371. X            perror("shutdown");
  1372. X        close(d->descriptor);
  1373. X    }
  1374. X    close(sock);
  1375. X}
  1376. X
  1377. Xvoid 
  1378. Xdump_users(struct descriptor_data * e)
  1379. X{
  1380. X    struct descriptor_data *d;
  1381. X    time_t          now;
  1382. X    racetype       *r;
  1383. X    int             God = 0;
  1384. X    int             coward_count = 0;
  1385. X
  1386. X    (void) time(&now);
  1387. X    sprintf(buf, "Current Players: %s", ctime(&now));
  1388. X    queue_string(e, buf);
  1389. X    if (e->Playernum) {
  1390. X        r = races[e->Playernum - 1];
  1391. X        God = r->God;
  1392. X    } else
  1393. X        return;
  1394. X
  1395. X    for (d = descriptor_list; d; d = d->next) {
  1396. X        if (d->connected) {
  1397. X            r = races[d->Playernum - 1];
  1398. X            if (!r->governor[d->Governor].toggle.invisible ||
  1399. X                e->Playernum == d->Playernum || God) {
  1400. X                sprintf(temp, "\"%s\"", r->governor[d->Governor].name);
  1401. X                sprintf(buf, "%20.20s %20.20s [%2d,%2d] %4ds idle %-4.4s %s %s\n",
  1402. X                   r->name, temp, d->Playernum, d->Governor,
  1403. X                    now - d->last_time,
  1404. X                    God ? Stars[Dir[d->Playernum - 1][d->Governor].snum]->name : "    ",
  1405. X                    (r->governor[d->Governor].toggle.gag ? "GAG" : "   "),
  1406. X                    (r->governor[d->Governor].toggle.invisible ? "INVISIBLE" : ""));
  1407. X                queue_string(e, buf);
  1408. X            } else if (!God)    /* deity lurks around */
  1409. X                coward_count++;
  1410. X
  1411. X            if ((now - d->last_time) > DISCONNECT_TIME)
  1412. X                d->connected = 0;
  1413. X        }
  1414. X    }
  1415. X#ifdef SHOW_COWARDS
  1416. X    sprintf(buf, "And %d coward%s.\n", coward_count, (coward_count == 1) ? "" : "s");
  1417. X    queue_string(e, buf);
  1418. X#endif
  1419. X    queue_string(e, "Finished.\n");
  1420. X}
  1421. X
  1422. Xvoid 
  1423. Xprocess_command(int Playernum, int Governor, char *comm)
  1424. X{
  1425. X    int             j, God, Guest;
  1426. X    char           *string;
  1427. X    racetype       *r;
  1428. X
  1429. X    /* determine which routine to go to and what action to take */
  1430. X    /*
  1431. X     * target routine is specified by the first substring, other options
  1432. X     * are the substrings which follow
  1433. X     */
  1434. X
  1435. X    r = races[Playernum - 1];
  1436. X    God = r->God;
  1437. X    Guest = r->Guest;
  1438. X
  1439. X    string = comm;
  1440. X    while (*string && *string != ' ')
  1441. X        string++;
  1442. X
  1443. X    if (match(args[0], "announce"))    /* keep this at the front */
  1444. X        announce(Playernum, Governor, string, ANN, 0);
  1445. X    else if (match(args[0], CSP_SERVER))
  1446. X        CSP_process_command(Playernum, Governor);
  1447. X    else if (match(args[0], "client_survey"))
  1448. X        survey(Playernum, Governor, 0, 1);
  1449. X    else if (match(args[0], "allocate"))
  1450. X        allocateAPs(Playernum, Governor, 0);
  1451. X    else if (match(args[0], "analysis"))
  1452. X        analysis(Playernum, Governor, 0);
  1453. X    else if (match(args[0], "arm"))
  1454. X        arm(Playernum, Governor, 0, 1);
  1455. X    else if (match(args[0], "disarm"))
  1456. X        arm(Playernum, Governor, 0, 0);
  1457. X    else if (match(args[0], "assault"))
  1458. X        dock(Playernum, Governor, 1, 1);
  1459. X    else if (match(args[0], "autoreport"))
  1460. X        autoreport(Playernum, Governor, 0);
  1461. X    else if (match(args[0], "build"))
  1462. X        build(Playernum, Governor, 1);
  1463. X#ifdef MARKET
  1464. X    else if (match(args[0], "bid"))
  1465. X        bid(Playernum, Governor, 0);
  1466. X    else if (match(args[0], "sell"))
  1467. X        sell(Playernum, Governor, 20);
  1468. X#endif
  1469. X    else if (match(args[0], "bless") && God)
  1470. X        bless(Playernum, Governor, 0);
  1471. X    else if (match(args[0], "'") || match(args[0], "broadcast"))
  1472. X        announce(Playernum, Governor, string, BROADCAST, 0);
  1473. X    else if (match(args[0], "shout") && God)
  1474. X        announce(Playernum, Governor, string, SHOUT, 0);
  1475. X    else if (match(args[0], "think"))
  1476. X        announce(Playernum, Governor, string, THINK, 0);
  1477. X    else if (match(args[0], "block"))
  1478. X        block(Playernum, Governor, 0);
  1479. X    else if (match(args[0], "bombard") && !Guest)
  1480. X        bombard(Playernum, Governor, 1);
  1481. X    else if (match(args[0], "cs"))
  1482. X        cs(Playernum, Governor, 0);
  1483. X    else if (match(args[0], "capital"))
  1484. X        capital(Playernum, Governor, 50);
  1485. X    else if (match(args[0], "capture"))
  1486. X        capture(Playernum, Governor, 1);
  1487. X    else if (match(args[0], "center"))
  1488. X        center(Playernum, Governor, 0);
  1489. X#ifdef MULTIPLE_COMM_CHANNELS
  1490. X    else if (match(args[0], "channel"))
  1491. X        channel(Playernum, Governor, 0, 0);
  1492. X    else if (match(args[0], "1"))
  1493. X        announce(Playernum, Governor, string, BROADCAST, 1);
  1494. X    else if (match(args[0], "2"))
  1495. X        announce(Playernum, Governor, string, BROADCAST, 2);
  1496. X    else if (match(args[0], "3"))
  1497. X        announce(Playernum, Governor, string, BROADCAST, 3);
  1498. X#endif 
  1499. X    else if (match(args[0], "declare"))
  1500. X        declare(Playernum, Governor, 1);
  1501. X#ifdef DEFENSE
  1502. X    else if (match(args[0], "defend"))
  1503. X        defend(Playernum, Governor, 1);
  1504. X#endif
  1505. X    else if (match(args[0], "detonate") && !Guest)
  1506. X        detonate(Playernum, Governor, 0);
  1507. X    else if (match(args[0], "distance"))
  1508. X        distance(Playernum, Governor, 0);
  1509. X    else if (match(args[0], "dismount"))
  1510. X        mount(Playernum, Governor, 0, 0);
  1511. X    else if (match(args[0], "dissolve") && !Guest)
  1512. X        dissolve(Playernum, Governor);
  1513. X    else if (match(args[0], "dock"))
  1514. X        dock(Playernum, Governor, 0, 0);
  1515. X    else if (match(args[0], "dump") && !Guest)
  1516. X        dump(Playernum, Governor, 10);
  1517. X    else if (match(args[0], "enslave"))
  1518. X        enslave(Playernum, Governor, 2);
  1519. X    else if (match(args[0], "examine"))
  1520. X        examine(Playernum, Governor, 0);
  1521. X    else if (match(args[0], "explore"))
  1522. X        exploration(Playernum, Governor, 0);
  1523. X    else if (match(args[0], "cew"))
  1524. X        fire(Playernum, Governor, 1, 1);
  1525. X    else if (match(args[0], "fire") && !Guest)
  1526. X        fire(Playernum, Governor, 1, 0);
  1527. X    else if (match(args[0], "fuel"))
  1528. X        proj_fuel(Playernum, Governor, 0);
  1529. X    else if (match(args[0], "governors") || match(args[0], "appoint")
  1530. X         || match(args[0], "revoke"))
  1531. X        governors(Playernum, Governor, 0);
  1532. X    else if (match(args[0], "grant"))
  1533. X        grant(Playernum, Governor, 0);
  1534. X    else if (match(args[0], "give") && !Guest)
  1535. X        give(Playernum, Governor, 5);
  1536. X    else if (match(args[0], "highlight"))
  1537. X        highlight(Playernum, Governor);
  1538. X    else if (match(args[0], "identify") || match(args[0], "whois"))
  1539. X        whois(Playernum, Governor, 0);
  1540. X#ifdef MARKET
  1541. X    else if (match(args[0], "insurgency"))
  1542. X        insurgency(Playernum, Governor, 10);
  1543. X#endif
  1544. X    else if (match(args[0], "invite"))
  1545. X        invite(Playernum, Governor, 0, 1);
  1546. X    else if (match(args[0], "jettison"))
  1547. X        jettison(Playernum, Governor, 0);
  1548. X    else if (match(args[0], "land"))
  1549. X        land(Playernum, Governor, 1);
  1550. X    else if (match(args[0], "launch"))
  1551. X        launch(Playernum, Governor, 0);
  1552. X    else if (match(args[0], "load"))
  1553. X        load(Playernum, Governor, 0, 0);
  1554. X    else if (match(args[0], "list"))
  1555. X        list(Playernum, Governor);
  1556. X    else if (match(args[0], "map"))
  1557. X        map(Playernum, Governor, 0);
  1558. X    else if (match(args[0], "mobilize"))
  1559. X        mobilize(Playernum, Governor, 1);
  1560. X    else if (match(args[0], "move"))
  1561. X        move_popn(Playernum, Governor, CIV);
  1562. X    else if (match(args[0], "deploy"))
  1563. X        move_popn(Playernum, Governor, MIL);
  1564. X    else if (match(args[0], "make"))
  1565. X        make_mod(Playernum, Governor, 0, 0);
  1566. X#ifdef DEBUG
  1567. X    else if (match(args[0], "memcheck") && God)
  1568. X        DEBUGcheck(Playernum, Governor);
  1569. X    else if (match(args[0], "memreset") && God)
  1570. X        DEBUGreset(Playernum, Governor);
  1571. X#endif
  1572. X    else if (match(args[0], "modify"))
  1573. X        make_mod(Playernum, Governor, 0, 1);
  1574. X    else if (match(args[0], "mount"))
  1575. X        mount(Playernum, Governor, 0, 1);
  1576. X    else if (match(args[0], "motto"))
  1577. X        motto(Playernum, Governor, 0, comm);
  1578. X    else if (match(args[0], "name"))
  1579. X        name(Playernum, Governor, 0);
  1580. X    else if (match(args[0], "orbit"))
  1581. X        orbit(Playernum, Governor, 0);
  1582. X    else if (match(args[0], "order"))
  1583. X        order(Playernum, Governor, 1);
  1584. X    else if (match(args[0], "page"))
  1585. X        page(Playernum, Governor, !God);
  1586. X    else if (match(args[0], "pay") && !Guest)
  1587. X        pay(Playernum, Governor, 0);
  1588. X    else if (match(args[0], "colonies"))
  1589. X        colonies(Playernum, Governor, 0, 0);
  1590. X    else if (match(args[0], "personal"))
  1591. X        personal(Playernum, Governor, string);
  1592. X    else if (match(args[0], "pledge"))
  1593. X        pledge(Playernum, Governor, 0, 1);
  1594. X    else if (match(args[0], "power"))
  1595. X        power(Playernum, Governor, 0);
  1596. X    else if (match(args[0], "post"))
  1597. X        send_message(Playernum, Governor, 0, 1);
  1598. X    else if (match(args[0], "profile"))
  1599. X        profile(Playernum, Governor, 0);
  1600. X    else if (match(args[0], "production"))
  1601. X        colonies(Playernum, Governor, 0, 1);
  1602. X    else if (match(args[0], "purge") && God)
  1603. X        purge();
  1604. X    else if (match(args[0], "fix") && God)
  1605. X        fix(Playernum, Governor);
  1606. X    else if (match(args[0], "relation"))
  1607. X        relation(Playernum, Governor, 0);
  1608. X    else if (match(args[0], "read"))
  1609. X        read_messages(Playernum, Governor, 0);
  1610. X    else if (match(args[0], "@@reset") && God) {
  1611. X        for (j = 1; j <= Num_races; j++)
  1612. X            if (!send_special_string(j, RESET_START))
  1613. X                notify_race(j, "DOING RESET...\n");
  1614. X        force_output();
  1615. X        load_race_data();
  1616. X        load_star_data();
  1617. X        do_reset(1);
  1618. X    } else if (match(args[0], "report"))
  1619. X        rst(Playernum, Governor, 0, 0);
  1620. X    else if (match(args[0], "factories"))
  1621. X        rst(Playernum, Governor, 0, 6);
  1622. X    else if (match(args[0], "repair"))
  1623. X        repair(Playernum, Governor, 0);
  1624. X    else if (match(args[0], "route"))
  1625. X        route(Playernum, Governor, 0);
  1626. X    else if (match(args[0], "@@shutdown") && God) {
  1627. X        shutdown_flag = 1;
  1628. X        notify(Playernum, Governor, "Doing shutdown.\n");
  1629. X    } else if (match(args[0], "@@update") && God)
  1630. X        do_update(1);
  1631. X    else if (match(args[0], "@@segment") && God)
  1632. X        do_segment(1, atoi(args[1]));
  1633. X    else if (match(args[0], "stock"))
  1634. X        rst(Playernum, Governor, 0, 1);
  1635. X    else if (match(args[0], "stats"))
  1636. X        rst(Playernum, Governor, 0, 4);
  1637. X    else if (match(args[0], "ship"))
  1638. X        rst(Playernum, Governor, 0, 3);
  1639. X    else if (match(args[0], "survey"))
  1640. X        survey(Playernum, Governor, 0, 0);
  1641. X    else if (match(args[0], "client_survey"))
  1642. X        survey(Playernum, Governor, 0, 1);
  1643. X    else if (match(args[0], "send"))
  1644. X        send_message(Playernum, Governor, !God, 0);
  1645. X    else if (match(args[0], "scrap") && (argn > 1))
  1646. X        scrap(Playernum, Governor, 1);
  1647. X    else if (match(args[0], "stars"))
  1648. X        star_locations(Playernum, Governor, 0);
  1649. X    else if (match(args[0], "status"))
  1650. X        tech_status(Playernum, Governor, 0);
  1651. X    else if (match(args[0], "tactical"))
  1652. X        rst(Playernum, Governor, 0, 2);
  1653. X#ifdef MARKET
  1654. X    else if (match(args[0], "tax"))
  1655. X        tax(Playernum, Governor, 0);
  1656. X#endif
  1657. X    else if (match(args[0], "technology"))
  1658. X        technology(Playernum, Governor, 1);
  1659. X    else if (match(args[0], "toggle"))
  1660. X        toggle(Playernum, Governor, 0);
  1661. X    else if (match(args[0], "toxicity"))
  1662. X        toxicity(Playernum, Governor, 1);
  1663. X#ifdef MARKET
  1664. X    else if (match(args[0], "treasury"))
  1665. X        treasury(Playernum, Governor);
  1666. X#endif
  1667. X    else if (match(args[0], "transfer") && !Guest)
  1668. X        transfer(Playernum, Governor, 1);
  1669. X    else if (match(args[0], "unload"))
  1670. X        load(Playernum, Governor, 0, 1);
  1671. X    else if (match(args[0], "undock"))
  1672. X        launch(Playernum, Governor, 1);
  1673. X    else if (match(args[0], "uninvite"))
  1674. X        invite(Playernum, Governor, 0, 0);
  1675. X    else if (match(args[0], "unpledge"))
  1676. X        pledge(Playernum, Governor, 0, 0);
  1677. X    else if (match(args[0], "upgrade"))
  1678. X        upgrade(Playernum, Governor, 1);
  1679. X    else if (match(args[0], "victory"))
  1680. X        victory(Playernum, Governor);
  1681. X    else if (match(args[0], "walk"))
  1682. X        walk(Playernum, Governor, 1);
  1683. X    else if (match(args[0], "weapons"))
  1684. X        rst(Playernum, Governor, 0, 5);
  1685. X    else if (match(args[0], "time"))
  1686. X        GB_time(Playernum, Governor);
  1687. X    else if (match(args[0], "schedule"))
  1688. X        GB_schedule(Playernum, Governor);
  1689. X#ifdef VOTING
  1690. X    else if (match(args[0], "vote"))
  1691. X        vote(Playernum, Governor, 0);
  1692. X#endif
  1693. X    else if (match(args[0], "zoom"))
  1694. X        zoom(Playernum, Governor);
  1695. X    else {
  1696. X        sprintf(buf, "'%s':illegal command error(%d).\n", args[0], *args[0]);
  1697. X        notify(Playernum, Governor, buf);
  1698. X    }
  1699. X
  1700. X    /* compute the prompt and send to the player */
  1701. X    do_prompt(Playernum, Governor);
  1702. X    sprintf(buf, "%s", Dir[Playernum - 1][Governor].prompt);
  1703. X    notify(Playernum, Governor, buf);
  1704. X}
  1705. X
  1706. X
  1707. Xvoid 
  1708. XGB_time(int Playernum, int Governor)
  1709. X{                /* report back the update status */
  1710. X    clk = time(0);
  1711. X    notify(Playernum, Governor, start_buf);
  1712. X    notify(Playernum, Governor, update_buf);
  1713. X    notify(Playernum, Governor, segment_buf);
  1714. X    sprintf(buf, "Current time    : %s", ctime(&clk));
  1715. X    notify(Playernum, Governor, buf);
  1716. X}
  1717. X
  1718. Xvoid 
  1719. Xkill_ship(int Playernum, shiptype * ship)
  1720. X{
  1721. X    planettype     *planet;
  1722. X    racetype       *killer, *victim;
  1723. X    shiptype       *s;
  1724. X    int             sh;
  1725. X
  1726. X    ship->alive = 0;
  1727. X    ship->notified = 0;    /* prepare the ship for recycling */
  1728. X
  1729. X    if (ship->type != STYPE_POD && ship->type != OTYPE_FACTORY) {
  1730. X        /* pods don't do things to morale, ditto for factories */
  1731. X        victim = races[ship->owner - 1];
  1732. X        if (victim->Gov_ship == ship->number)
  1733. X            victim->Gov_ship = 0;
  1734. X        if (!victim->God && Playernum != ship->owner) {
  1735. X            killer = races[Playernum - 1];
  1736. X            adjust_morale(killer, victim, (int) ship->build_cost);
  1737. X            putrace(killer);
  1738. X        } else if (ship->owner == Playernum && !ship->docked && Max_crew(ship)) {
  1739. X            victim->morale -= 2 * ship->build_cost;    /* scuttle/scrap */
  1740. X        }
  1741. X        putrace(victim);
  1742. X    }
  1743. X    if (ship->type == OTYPE_TOXWC && ship->whatorbits == LEVEL_PLAN) {
  1744. X        getplanet(&planet, (int) ship->storbits, (int) ship->pnumorbits);
  1745. X        planet->conditions[TOXIC] = MIN(100, planet->conditions[TOXIC] +
  1746. X                        ship->special.waste.toxic);
  1747. X        putplanet(planet, (int) ship->storbits, (int) ship->pnumorbits);
  1748. X    }
  1749. X    /* undock the stuff docked with it */
  1750. X    if (ship->docked && ship->whatorbits != LEVEL_SHIP
  1751. X        && ship->whatdest == LEVEL_SHIP) {
  1752. X        (void) getship(&s, (int) ship->destshipno);
  1753. X        s->docked = 0;
  1754. X        s->whatdest = LEVEL_UNIV;
  1755. X        putship(s);
  1756. X        free(s);
  1757. X    }
  1758. X    /* landed ships are killed */
  1759. X    if (ship->ships) {
  1760. X        sh = ship->ships;
  1761. X        while (sh) {
  1762. X            (void) getship(&s, sh);
  1763. X            kill_ship(Playernum, s);
  1764. X            putship(s);
  1765. X            sh = s->nextship;
  1766. X            free(s);
  1767. X        }
  1768. X    }
  1769. X}
  1770. X
  1771. Xvoid 
  1772. Xcompute_power_blocks(void)
  1773. X{
  1774. X    int             i, j, dummy[2];
  1775. X    /* compute alliance block power */
  1776. X    sprintf(Power_blocks.time, "%s", ctime(&clk));
  1777. X    for (i = 1; i <= Num_races; i++) {
  1778. X        dummy[0] = (Blocks[i - 1].invite[0] & Blocks[i - 1].pledge[0]);
  1779. X        dummy[1] = (Blocks[i - 1].invite[1] & Blocks[i - 1].pledge[1]);
  1780. X        Power_blocks.members[i - 1] = 0;
  1781. X        Power_blocks.sectors_owned[i - 1] = 0;
  1782. X        Power_blocks.popn[i - 1] = 0;
  1783. X        Power_blocks.ships_owned[i - 1] = 0;
  1784. X        Power_blocks.resource[i - 1] = 0;
  1785. X        Power_blocks.fuel[i - 1] = 0;
  1786. X        Power_blocks.destruct[i - 1] = 0;
  1787. X        Power_blocks.money[i - 1] = 0;
  1788. X        Power_blocks.systems_owned[i - 1] = Blocks[i - 1].systems_owned;
  1789. X        Power_blocks.VPs[i - 1] = Blocks[i - 1].VPs;
  1790. X        for (j = 1; j <= Num_races; j++)
  1791. X            if (isset(dummy, j)) {
  1792. X                Power_blocks.members[i - 1] += 1;
  1793. X                Power_blocks.sectors_owned[i - 1] += Power[j - 1].sectors_owned;
  1794. X                Power_blocks.money[i - 1] += Power[j - 1].money;
  1795. X                Power_blocks.popn[i - 1] += Power[j - 1].popn;
  1796. X                Power_blocks.ships_owned[i - 1] += Power[j - 1].ships_owned;
  1797. X                Power_blocks.resource[i - 1] += Power[j - 1].resource;
  1798. X                Power_blocks.fuel[i - 1] += Power[j - 1].fuel;
  1799. X                Power_blocks.destruct[i - 1] += Power[j - 1].destruct;
  1800. X            }
  1801. X    }
  1802. X}
  1803. X
  1804. X
  1805. Xvoid 
  1806. Xwarn_race(int who, char *message)
  1807. X{
  1808. X    reg int         i;
  1809. X
  1810. X    for (i = 0; i <= MAXGOVERNORS; i++)
  1811. X        if (races[who - 1]->governor[i].active)
  1812. X            warn(who, i, message);
  1813. X}
  1814. X
  1815. Xvoid 
  1816. Xwarn(int who, int governor, char *message)
  1817. X{
  1818. X    if (!notify(who, governor, message) && !notify(who, 0, message))
  1819. X        push_telegram(who, governor, message);
  1820. X}
  1821. X
  1822. Xvoid 
  1823. Xwarn_star(int a, int b, int star, char *message)
  1824. X{
  1825. X    int             i;
  1826. X
  1827. X    for (i = 1; i <= Num_races; i++)
  1828. X        if (i != a && i != b && isset(Stars[star]->inhabited, i))
  1829. X            warn_race(i, message);
  1830. X}
  1831. X
  1832. Xvoid 
  1833. Xnotify_star(int a, int g, int b, int star, char *message)
  1834. X{
  1835. X    struct descriptor_data *d;
  1836. X    racetype       *Race;
  1837. X
  1838. X#ifdef MONITOR
  1839. X    Race = races[0];    /* deity */
  1840. X    if (Race->monitor || (a != 1 && b != 1))
  1841. X        notify_race(1, message);
  1842. X#endif
  1843. X    for (d = descriptor_list; d; d = d->next)
  1844. X        if (d->connected && (d->Playernum != a || d->Governor != g) &&
  1845. X            isset(Stars[star]->inhabited, d->Playernum)) {
  1846. X            queue_string(d, message);
  1847. X        }
  1848. X}
  1849. END_OF_FILE
  1850. if test 48398 -ne `wc -c <'server/GB_server.c'`; then
  1851.     echo shar: \"'server/GB_server.c'\" unpacked with wrong size!
  1852. fi
  1853. # end of 'server/GB_server.c'
  1854. fi
  1855. if test -f 'server/access.c' -a "${1}" != "-c" ; then 
  1856.   echo shar: Will not clobber existing file \"'server/access.c'\"
  1857. else
  1858. echo shar: Extracting \"'server/access.c'\" \(2956 characters\)
  1859. sed "s/^X//" >'server/access.c' <<'END_OF_FILE'
  1860. X#include <stdio.h>
  1861. X#include <sys/types.h>
  1862. X#include <sys/file.h>
  1863. X#include <sys/time.h>
  1864. X#include <signal.h>
  1865. X#include <sys/ioctl.h>
  1866. X#include <sys/wait.h>
  1867. X#include <fcntl.h>
  1868. X#include <sys/errno.h>
  1869. X#include <ctype.h>
  1870. X#include <sys/socket.h>
  1871. X#include <netinet/in.h>
  1872. X#include <netdb.h>
  1873. X
  1874. X#include <curses.h>
  1875. X#include <strings.h>
  1876. X#include <pwd.h>
  1877. X
  1878. X#include <sys/uio.h>
  1879. X#include <sys/timeb.h>
  1880. X
  1881. X#include "interface.h"
  1882. X#include "files.h"
  1883. X
  1884. X/*
  1885. X * Prototypes
  1886. X */
  1887. Xint             address_ok(struct sockaddr_in *);
  1888. Xint             address_match(struct in_addr *, struct in_addr *);
  1889. Xvoid            add_address(unsigned long, int);
  1890. X
  1891. Xstatic int      naddresses = 0;
  1892. Xtypedef struct access {
  1893. X    struct in_addr  ac_addr;
  1894. X    int             access_value;
  1895. X}               ac_t;
  1896. Xstatic ac_t    *ac_tab = (ac_t *) NULL;
  1897. X
  1898. Xint 
  1899. Xaddress_ok(struct sockaddr_in * ap)
  1900. X{
  1901. X    register int    i;
  1902. X    register ac_t  *acp;
  1903. X    static int      ainit = 0;
  1904. X    FILE           *afile;
  1905. X    char           *cp, ibuf[64];
  1906. X    int             aval;
  1907. X    unsigned long   ina;
  1908. X
  1909. X    if (!ainit) {
  1910. X        ainit = 1;
  1911. X        if ((afile = fopen(ADDRESSFL, "r"))) {
  1912. X            while (fgets(ibuf, sizeof ibuf, afile)) {
  1913. X                cp = ibuf;
  1914. X                aval = 1;
  1915. X                if (*cp == '#' || *cp == '\n' || *cp == '\r')
  1916. X                    continue;
  1917. X                if (*cp == '!') {
  1918. X                    cp++;
  1919. X                    aval = 0;
  1920. X                }
  1921. X                ina = inet_addr(cp);
  1922. X                if (ina != -1)
  1923. X                    add_address(ina, aval);
  1924. X            }
  1925. X            fclose(afile);
  1926. X            /* Always allow localhost. */
  1927. X            add_address(inet_addr("127"), 1);
  1928. X        } else {
  1929. X            /* Allow anything. */
  1930. X            add_address(inet_addr("0"), 1);
  1931. X        }
  1932. X    }
  1933. X    acp = ac_tab;
  1934. X    for (i = 0; i < naddresses; i++, acp++) {
  1935. X        if (address_match((struct in_addr *)&ap->sin_addr.s_addr, &acp->ac_addr))
  1936. X            return acp->access_value;
  1937. X    }
  1938. X    return 0;
  1939. X}
  1940. X
  1941. Xaddress_match(struct in_addr * addr, struct in_addr * apat)
  1942. X{
  1943. X    /* Ugh!  There HAS to be a better way... */
  1944. X
  1945. X    if (!apat->S_un.S_un_b.s_b1) {
  1946. X        if (apat->S_un.S_un_b.s_b4 &&
  1947. X            apat->S_un.S_un_b.s_b4 != addr->S_un.S_un_b.s_b1)
  1948. X            return 0;
  1949. X        return 1;
  1950. X    } else {
  1951. X        if (apat->S_un.S_un_b.s_b1 != addr->S_un.S_un_b.s_b1)
  1952. X            return 0;
  1953. X    }
  1954. X    if (!apat->S_un.S_un_b.s_b2) {
  1955. X        if (apat->S_un.S_un_b.s_b4 &&
  1956. X            apat->S_un.S_un_b.s_b4 != addr->S_un.S_un_b.s_b2)
  1957. X            return 0;
  1958. X        return 1;
  1959. X    } else {
  1960. X        if (apat->S_un.S_un_b.s_b2 != addr->S_un.S_un_b.s_b2)
  1961. X            return 0;
  1962. X    }
  1963. X    if (!apat->S_un.S_un_b.s_b3) {
  1964. X        if (apat->S_un.S_un_b.s_b4 &&
  1965. X            apat->S_un.S_un_b.s_b4 != addr->S_un.S_un_b.s_b3)
  1966. X            return 0;
  1967. X        return 1;
  1968. X    } else {
  1969. X        if (apat->S_un.S_un_b.s_b3 != addr->S_un.S_un_b.s_b3)
  1970. X            return 0;
  1971. X    }
  1972. X    if (apat->S_un.S_un_b.s_b4 != addr->S_un.S_un_b.s_b4)
  1973. X        return 0;
  1974. X    return 1;
  1975. X}
  1976. X
  1977. Xvoid 
  1978. Xadd_address(unsigned long ina, int aval)
  1979. X{
  1980. X    register ac_t  *nac_t;
  1981. X
  1982. X    if (naddresses > 0)
  1983. X        nac_t = (ac_t *) realloc(ac_tab, sizeof(ac_t) * (naddresses + 1));
  1984. X    else
  1985. X        nac_t = (ac_t *) calloc(1, sizeof(ac_t));
  1986. X    if (!nac_t) {
  1987. X        printf("add_address: Out of memory.\n");
  1988. X        return;
  1989. X    }
  1990. X    ac_tab = nac_t;
  1991. X    nac_t = &ac_tab[naddresses++];
  1992. X    nac_t->ac_addr.s_addr = ina;
  1993. X    nac_t->access_value = aval;
  1994. X}
  1995. END_OF_FILE
  1996. if test 2956 -ne `wc -c <'server/access.c'`; then
  1997.     echo shar: \"'server/access.c'\" unpacked with wrong size!
  1998. fi
  1999. # end of 'server/access.c'
  2000. fi
  2001. echo shar: End of archive 3 \(of 21\).
  2002. cp /dev/null ark3isdone
  2003. MISSING=""
  2004. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ; do
  2005.     if test ! -f ark${I}isdone ; then
  2006.     MISSING="${MISSING} ${I}"
  2007.     fi
  2008. done
  2009. if test "${MISSING}" = "" ; then
  2010.     echo You have unpacked all 21 archives.
  2011.     echo "Now type './buildfiles.sh'"
  2012.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2013. else
  2014.     echo You still need to unpack the following archives:
  2015.     echo "        " ${MISSING}
  2016. fi
  2017. ##  End of shell archive.
  2018. exit 0
  2019.