| File: | src/games/hunt/huntd/answer.c |
| Warning: | line 172, column 2 Value stored to 'cp1' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* $OpenBSD: answer.c,v 1.22 2017/01/21 08:22:57 krw Exp $ */ |
| 2 | /* $NetBSD: answer.c,v 1.3 1997/10/10 16:32:50 lukem Exp $ */ |
| 3 | /* |
| 4 | * Copyright (c) 1983-2003, Regents of the University of California. |
| 5 | * All rights reserved. |
| 6 | * |
| 7 | * Redistribution and use in source and binary forms, with or without |
| 8 | * modification, are permitted provided that the following conditions are |
| 9 | * met: |
| 10 | * |
| 11 | * + Redistributions of source code must retain the above copyright |
| 12 | * notice, this list of conditions and the following disclaimer. |
| 13 | * + Redistributions in binary form must reproduce the above copyright |
| 14 | * notice, this list of conditions and the following disclaimer in the |
| 15 | * documentation and/or other materials provided with the distribution. |
| 16 | * + Neither the name of the University of California, San Francisco nor |
| 17 | * the names of its contributors may be used to endorse or promote |
| 18 | * products derived from this software without specific prior written |
| 19 | * permission. |
| 20 | * |
| 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS |
| 22 | * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
| 23 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
| 24 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 25 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 26 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 27 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 32 | */ |
| 33 | |
| 34 | #include <sys/select.h> |
| 35 | |
| 36 | #include <arpa/inet.h> |
| 37 | #include <netinet/in.h> |
| 38 | |
| 39 | #include <ctype.h> |
| 40 | #include <fcntl.h> |
| 41 | #include <stdlib.h> |
| 42 | #include <string.h> |
| 43 | #include <syslog.h> |
| 44 | #include <unistd.h> |
| 45 | |
| 46 | #include "conf.h" |
| 47 | #include "hunt.h" |
| 48 | #include "server.h" |
| 49 | |
| 50 | /* Exported symbols for hosts_access(): */ |
| 51 | int allow_severity = LOG_INFO6; |
| 52 | int deny_severity = LOG_WARNING4; |
| 53 | |
| 54 | |
| 55 | /* List of spawning connections: */ |
| 56 | struct spawn *Spawn = NULL((void *)0); |
| 57 | |
| 58 | static void stplayer(PLAYER *, int); |
| 59 | static void stmonitor(PLAYER *); |
| 60 | static IDENT * get_ident(struct sockaddr *, int, u_long, char *, char); |
| 61 | |
| 62 | void |
| 63 | answer_first(void) |
| 64 | { |
| 65 | struct sockaddr sockstruct; |
| 66 | int newsock; |
| 67 | socklen_t socklen; |
| 68 | struct spawn *sp; |
| 69 | |
| 70 | /* |
| 71 | * Answer the call to hunt, turning off blocking I/O, so a slow |
| 72 | * or dead terminal won't stop the game. All subsequent reads |
| 73 | * check how many bytes they read. |
| 74 | */ |
| 75 | socklen = sizeof sockstruct; |
| 76 | newsock = accept4(Socket, (struct sockaddr *) &sockstruct, &socklen, |
| 77 | SOCK_NONBLOCK0x4000); |
| 78 | if (newsock < 0) { |
| 79 | logit(LOG_ERR3, "accept"); |
| 80 | return; |
| 81 | } |
| 82 | |
| 83 | /* Remember this spawning connection: */ |
| 84 | sp = calloc(1, sizeof *sp); |
| 85 | if (sp == NULL((void *)0)) { |
| 86 | logit(LOG_ERR3, "calloc"); |
| 87 | close(newsock); |
| 88 | return; |
| 89 | } |
| 90 | |
| 91 | /* Keep the calling machine's source addr for ident purposes: */ |
| 92 | memcpy(&sp->source, &sockstruct, sizeof sp->source); |
| 93 | sp->sourcelen = socklen; |
| 94 | |
| 95 | /* Warn if we lose connection info: */ |
| 96 | if (socklen > sizeof Spawn->source) |
| 97 | logx(LOG_WARNING4, |
| 98 | "struct sockaddr is not big enough! (%d > %zu)", |
| 99 | socklen, sizeof Spawn->source); |
| 100 | |
| 101 | /* Start listening to the spawning connection */ |
| 102 | sp->fd = newsock; |
| 103 | FD_SET(sp->fd, &Fds_mask)__fd_set((sp->fd), (&Fds_mask)); |
| 104 | if (sp->fd >= Num_fds) |
| 105 | Num_fds = sp->fd + 1; |
| 106 | |
| 107 | sp->reading_msg = 0; |
| 108 | sp->inlen = 0; |
| 109 | |
| 110 | /* Add to the spawning list */ |
| 111 | if ((sp->next = Spawn) != NULL((void *)0)) |
| 112 | Spawn->prevnext = &sp->next; |
| 113 | sp->prevnext = &Spawn; |
| 114 | Spawn = sp; |
| 115 | } |
| 116 | |
| 117 | int |
| 118 | answer_next(struct spawn *sp) |
| 119 | { |
| 120 | PLAYER *pp; |
| 121 | char *cp1, *cp2; |
| 122 | u_int32_t version; |
| 123 | FILE *conn; |
| 124 | int len; |
| 125 | char teamstr[] = "[x]"; |
| 126 | |
| 127 | if (sp->reading_msg) { |
| 128 | /* Receive a message from a player */ |
| 129 | len = read(sp->fd, sp->msg + sp->msglen, |
| 130 | sizeof sp->msg - sp->msglen); |
| 131 | if (len < 0) |
| 132 | goto error; |
| 133 | sp->msglen += len; |
| 134 | if (len && sp->msglen < sizeof sp->msg) |
| 135 | return FALSE0; |
| 136 | |
| 137 | teamstr[1] = sp->team; |
| 138 | outyx(ALL_PLAYERS((PLAYER *)1), HEIGHT23, 0, "%s%s: %.*s", |
| 139 | sp->name, |
| 140 | sp->team == ' ' ? "": teamstr, |
| 141 | sp->msglen, |
| 142 | sp->msg); |
| 143 | ce(ALL_PLAYERS((PLAYER *)1)); |
| 144 | sendcom(ALL_PLAYERS((PLAYER *)1), REFRESH('r' | 0200)); |
| 145 | sendcom(ALL_PLAYERS((PLAYER *)1), READY('g' | 0200), 0); |
| 146 | flush(ALL_PLAYERS((PLAYER *)1)); |
| 147 | goto close_it; |
| 148 | } |
| 149 | |
| 150 | /* Fill the buffer */ |
| 151 | len = read(sp->fd, sp->inbuf + sp->inlen, |
| 152 | sizeof sp->inbuf - sp->inlen); |
| 153 | if (len <= 0) |
| 154 | goto error; |
| 155 | sp->inlen += len; |
| 156 | if (sp->inlen < sizeof sp->inbuf) |
| 157 | return FALSE0; |
| 158 | |
| 159 | /* Extract values from the buffer */ |
| 160 | cp1 = sp->inbuf; |
| 161 | memcpy(&sp->uid, cp1, sizeof (u_int32_t)); |
| 162 | cp1+= sizeof(u_int32_t); |
| 163 | memcpy(sp->name, cp1, NAMELEN20); |
| 164 | cp1+= NAMELEN20; |
| 165 | memcpy(&sp->team, cp1, sizeof (u_int8_t)); |
| 166 | cp1+= sizeof(u_int8_t); |
| 167 | memcpy(&sp->enter_status, cp1, sizeof (u_int32_t)); |
| 168 | cp1+= sizeof(u_int32_t); |
| 169 | memcpy(sp->ttyname, cp1, NAMELEN20); |
| 170 | cp1+= NAMELEN20; |
| 171 | memcpy(&sp->mode, cp1, sizeof (u_int32_t)); |
| 172 | cp1+= sizeof(u_int32_t); |
Value stored to 'cp1' is never read | |
| 173 | |
| 174 | /* Convert data from network byte order: */ |
| 175 | sp->uid = ntohl(sp->uid)(__uint32_t)(__builtin_constant_p(sp->uid) ? (__uint32_t)( ((__uint32_t)(sp->uid) & 0xff) << 24 | ((__uint32_t )(sp->uid) & 0xff00) << 8 | ((__uint32_t)(sp-> uid) & 0xff0000) >> 8 | ((__uint32_t)(sp->uid) & 0xff000000) >> 24) : __swap32md(sp->uid)); |
| 176 | sp->enter_status = ntohl(sp->enter_status)(__uint32_t)(__builtin_constant_p(sp->enter_status) ? (__uint32_t )(((__uint32_t)(sp->enter_status) & 0xff) << 24 | ((__uint32_t)(sp->enter_status) & 0xff00) << 8 | ((__uint32_t)(sp->enter_status) & 0xff0000) >> 8 | ((__uint32_t)(sp->enter_status) & 0xff000000) >> 24) : __swap32md(sp->enter_status)); |
| 177 | sp->mode = ntohl(sp->mode)(__uint32_t)(__builtin_constant_p(sp->mode) ? (__uint32_t) (((__uint32_t)(sp->mode) & 0xff) << 24 | ((__uint32_t )(sp->mode) & 0xff00) << 8 | ((__uint32_t)(sp-> mode) & 0xff0000) >> 8 | ((__uint32_t)(sp->mode) & 0xff000000) >> 24) : __swap32md(sp->mode)); |
| 178 | |
| 179 | /* |
| 180 | * Make sure the name contains only printable characters |
| 181 | * since we use control characters for cursor control |
| 182 | * between driver and player processes |
| 183 | */ |
| 184 | sp->name[NAMELEN20] = '\0'; |
| 185 | for (cp1 = cp2 = sp->name; *cp1 != '\0'; cp1++) |
| 186 | if (isprint((unsigned char)*cp1) || *cp1 == ' ') |
| 187 | *cp2++ = *cp1; |
| 188 | *cp2 = '\0'; |
| 189 | |
| 190 | /* Make sure team name is valid */ |
| 191 | if (sp->team < '1' || sp->team > '9') |
| 192 | sp->team = ' '; |
| 193 | |
| 194 | /* Tell the other end this server's hunt driver version: */ |
| 195 | version = htonl((u_int32_t) HUNT_VERSION)(__uint32_t)(__builtin_constant_p((u_int32_t) (-1)) ? (__uint32_t )(((__uint32_t)((u_int32_t) (-1)) & 0xff) << 24 | ( (__uint32_t)((u_int32_t) (-1)) & 0xff00) << 8 | ((__uint32_t )((u_int32_t) (-1)) & 0xff0000) >> 8 | ((__uint32_t )((u_int32_t) (-1)) & 0xff000000) >> 24) : __swap32md ((u_int32_t) (-1))); |
| 196 | (void) write(sp->fd, &version, sizeof version); |
| 197 | |
| 198 | if (sp->mode == C_MESSAGE2) { |
| 199 | /* The clients only wants to send a message: */ |
| 200 | sp->msglen = 0; |
| 201 | sp->reading_msg = 1; |
| 202 | return FALSE0; |
| 203 | } |
| 204 | |
| 205 | /* Use a stdio file descriptor from now on: */ |
| 206 | conn = fdopen(sp->fd, "w"); |
| 207 | |
| 208 | /* The player is a monitor: */ |
| 209 | if (sp->mode == C_MONITOR1) { |
| 210 | if (conf_monitor && End_monitor < &Monitor[MAXMON2]) { |
| 211 | pp = End_monitor++; |
| 212 | if (sp->team == ' ') |
| 213 | sp->team = '*'; |
| 214 | } else { |
| 215 | /* Too many monitors */ |
| 216 | fprintf(conn, "Too many monitors\n"); |
| 217 | fflush(conn); |
| 218 | logx(LOG_NOTICE5, "too many monitors"); |
| 219 | goto close_it; |
| 220 | } |
| 221 | |
| 222 | /* The player is a normal hunter: */ |
| 223 | } else { |
| 224 | if (End_player < &Player[MAXPL14]) |
| 225 | pp = End_player++; |
| 226 | else { |
| 227 | fprintf(conn, "Too many players\n"); |
| 228 | fflush(conn); |
| 229 | /* Too many players */ |
| 230 | logx(LOG_NOTICE5, "too many players"); |
| 231 | goto close_it; |
| 232 | } |
| 233 | } |
| 234 | |
| 235 | /* Find the player's running scorecard */ |
| 236 | pp->p_ident = get_ident(&sp->source, sp->sourcelen, sp->uid, |
| 237 | sp->name, sp->team); |
| 238 | pp->p_output = conn; |
| 239 | pp->p_death[0] = '\0'; |
| 240 | pp->p_fd = sp->fd; |
| 241 | |
| 242 | /* No idea where the player starts: */ |
| 243 | pp->p_y = 0; |
| 244 | pp->p_x = 0; |
| 245 | |
| 246 | /* Mode-specific initialisation: */ |
| 247 | if (sp->mode == C_MONITOR1) |
| 248 | stmonitor(pp); |
| 249 | else |
| 250 | stplayer(pp, sp->enter_status); |
| 251 | |
| 252 | /* And, they're off! Caller should remove and free sp. */ |
| 253 | return TRUE1; |
| 254 | |
| 255 | error: |
| 256 | if (len < 0) |
| 257 | logit(LOG_WARNING4, "read"); |
| 258 | else |
| 259 | logx(LOG_WARNING4, "lost connection to new client"); |
| 260 | |
| 261 | close_it: |
| 262 | /* Destroy the spawn */ |
| 263 | *sp->prevnext = sp->next; |
| 264 | if (sp->next) sp->next->prevnext = sp->prevnext; |
| 265 | FD_CLR(sp->fd, &Fds_mask)__fd_clr((sp->fd), (&Fds_mask)); |
| 266 | close(sp->fd); |
| 267 | free(sp); |
| 268 | return FALSE0; |
| 269 | } |
| 270 | |
| 271 | /* Start a monitor: */ |
| 272 | static void |
| 273 | stmonitor(PLAYER *pp) |
| 274 | { |
| 275 | |
| 276 | /* Monitors get to see the entire maze: */ |
| 277 | memcpy(pp->p_maze, Maze, sizeof pp->p_maze); |
| 278 | drawmaze(pp); |
| 279 | |
| 280 | /* Put the monitor's name near the bottom right on all screens: */ |
| 281 | outyx(ALL_PLAYERS((PLAYER *)1), |
| 282 | STAT_MON_ROW(5 + 14 + 1) + 1 + (pp - Monitor), STAT_NAME_COL61, |
| 283 | "%5.5s%c%-10.10s %c", " ", |
| 284 | stat_char(pp)(((pp)->p_flying < 0) ? (((pp)->p_cloak < 0) ? (( (pp)->p_scan < 0) ? ' ' : '*') : '+') : '&'), pp->p_ident->i_name, pp->p_ident->i_team); |
| 285 | |
| 286 | /* Ready the monitor: */ |
| 287 | sendcom(pp, REFRESH('r' | 0200)); |
| 288 | sendcom(pp, READY('g' | 0200), 0); |
| 289 | flush(pp); |
| 290 | } |
| 291 | |
| 292 | /* Start a player: */ |
| 293 | static void |
| 294 | stplayer(PLAYER *newpp, int enter_status) |
| 295 | { |
| 296 | int x, y; |
| 297 | PLAYER *pp; |
| 298 | int len; |
| 299 | |
| 300 | Nplayer++; |
| 301 | |
| 302 | for (y = 0; y < UBOUND1; y++) |
| 303 | for (x = 0; x < WIDTH51; x++) |
| 304 | newpp->p_maze[y][x] = Maze[y][x]; |
| 305 | for ( ; y < DBOUND(23 - 1); y++) { |
| 306 | for (x = 0; x < LBOUND1; x++) |
| 307 | newpp->p_maze[y][x] = Maze[y][x]; |
| 308 | for ( ; x < RBOUND(51 - 1); x++) |
| 309 | newpp->p_maze[y][x] = SPACE' '; |
| 310 | for ( ; x < WIDTH51; x++) |
| 311 | newpp->p_maze[y][x] = Maze[y][x]; |
| 312 | } |
| 313 | for ( ; y < HEIGHT23; y++) |
| 314 | for (x = 0; x < WIDTH51; x++) |
| 315 | newpp->p_maze[y][x] = Maze[y][x]; |
| 316 | |
| 317 | /* Drop the new player somewhere in the maze: */ |
| 318 | do { |
| 319 | x = rand_num(WIDTH51 - 1) + 1; |
| 320 | y = rand_num(HEIGHT23 - 1) + 1; |
| 321 | } while (Maze[y][x] != SPACE' '); |
| 322 | newpp->p_over = SPACE' '; |
| 323 | newpp->p_x = x; |
| 324 | newpp->p_y = y; |
| 325 | newpp->p_undershot = FALSE0; |
| 326 | |
| 327 | /* Send them flying if needed */ |
| 328 | if (enter_status == Q_FLY2 && conf_fly) { |
| 329 | newpp->p_flying = rand_num(conf_flytime); |
| 330 | newpp->p_flyx = 2 * rand_num(conf_flystep + 1) - conf_flystep; |
| 331 | newpp->p_flyy = 2 * rand_num(conf_flystep + 1) - conf_flystep; |
| 332 | newpp->p_face = FLYER'&'; |
| 333 | } else { |
| 334 | newpp->p_flying = -1; |
| 335 | newpp->p_face = rand_dir(); |
| 336 | } |
| 337 | |
| 338 | /* Initialize the new player's attributes: */ |
| 339 | newpp->p_damage = 0; |
| 340 | newpp->p_damcap = conf_maxdam; |
| 341 | newpp->p_nchar = 0; |
| 342 | newpp->p_ncount = 0; |
| 343 | newpp->p_nexec = 0; |
| 344 | newpp->p_ammo = conf_ishots; |
| 345 | newpp->p_nboots = 0; |
| 346 | |
| 347 | /* Decide on what cloak/scan status to enter with */ |
| 348 | if (enter_status == Q_SCAN3 && conf_scan) { |
| 349 | newpp->p_scan = conf_scanlen * Nplayer; |
| 350 | newpp->p_cloak = 0; |
| 351 | } else if (conf_cloak) { |
| 352 | newpp->p_scan = 0; |
| 353 | newpp->p_cloak = conf_cloaklen; |
| 354 | } else { |
| 355 | newpp->p_scan = 0; |
| 356 | newpp->p_cloak = 0; |
| 357 | } |
| 358 | newpp->p_ncshot = 0; |
| 359 | |
| 360 | /* |
| 361 | * For each new player, place a large mine and |
| 362 | * a small mine somewhere in the maze: |
| 363 | */ |
| 364 | do { |
| 365 | x = rand_num(WIDTH51 - 1) + 1; |
| 366 | y = rand_num(HEIGHT23 - 1) + 1; |
| 367 | } while (Maze[y][x] != SPACE' '); |
| 368 | Maze[y][x] = GMINE'g'; |
| 369 | for (pp = Monitor; pp < End_monitor; pp++) |
| 370 | check(pp, y, x); |
| 371 | |
| 372 | do { |
| 373 | x = rand_num(WIDTH51 - 1) + 1; |
| 374 | y = rand_num(HEIGHT23 - 1) + 1; |
| 375 | } while (Maze[y][x] != SPACE' '); |
| 376 | Maze[y][x] = MINE';'; |
| 377 | for (pp = Monitor; pp < End_monitor; pp++) |
| 378 | check(pp, y, x); |
| 379 | |
| 380 | /* Create a score line for the new player: */ |
| 381 | (void) snprintf(Buf, sizeof Buf, "%5.2f%c%-10.10s %c", |
| 382 | newpp->p_ident->i_score, stat_char(newpp)(((newpp)->p_flying < 0) ? (((newpp)->p_cloak < 0 ) ? (((newpp)->p_scan < 0) ? ' ' : '*') : '+') : '&' ), |
| 383 | newpp->p_ident->i_name, newpp->p_ident->i_team); |
| 384 | len = strlen(Buf); |
| 385 | y = STAT_PLAY_ROW5 + 1 + (newpp - Player); |
| 386 | for (pp = Player; pp < End_player; pp++) { |
| 387 | if (pp != newpp) { |
| 388 | /* Give everyone a few more shots: */ |
| 389 | pp->p_ammo += conf_nshots; |
| 390 | newpp->p_ammo += conf_nshots; |
| 391 | outyx(pp, y, STAT_NAME_COL61, Buf, len); |
| 392 | ammo_update(pp); |
| 393 | } |
| 394 | } |
| 395 | for (pp = Monitor; pp < End_monitor; pp++) |
| 396 | outyx(pp, y, STAT_NAME_COL61, Buf, len); |
| 397 | |
| 398 | /* Show the new player what they can see and where they are: */ |
| 399 | drawmaze(newpp); |
| 400 | drawplayer(newpp, TRUE1); |
| 401 | look(newpp); |
| 402 | |
| 403 | /* Make sure that the position they enter in will be erased: */ |
| 404 | if (enter_status == Q_FLY2 && conf_fly) |
| 405 | showexpl(newpp->p_y, newpp->p_x, FLYER'&'); |
| 406 | |
| 407 | /* Ready the new player: */ |
| 408 | sendcom(newpp, REFRESH('r' | 0200)); |
| 409 | sendcom(newpp, READY('g' | 0200), 0); |
| 410 | flush(newpp); |
| 411 | } |
| 412 | |
| 413 | /* |
| 414 | * rand_dir: |
| 415 | * Return a random direction |
| 416 | */ |
| 417 | int |
| 418 | rand_dir(void) |
| 419 | { |
| 420 | switch (rand_num(4)) { |
| 421 | case 0: |
| 422 | return LEFTS'{'; |
| 423 | case 1: |
| 424 | return RIGHT'}'; |
| 425 | case 2: |
| 426 | return BELOW'!'; |
| 427 | case 3: |
| 428 | return ABOVE'i'; |
| 429 | } |
| 430 | return(-1); |
| 431 | } |
| 432 | |
| 433 | /* |
| 434 | * get_ident: |
| 435 | * Get the score structure of a player |
| 436 | */ |
| 437 | static IDENT * |
| 438 | get_ident(struct sockaddr *sa, int salen, u_long uid, char *name, char team) |
| 439 | { |
| 440 | IDENT *ip; |
| 441 | static IDENT punt; |
| 442 | u_int32_t machine; |
| 443 | |
| 444 | if (sa->sa_family == AF_INET2) |
| 445 | machine = ntohl((u_long)((struct sockaddr_in *)sa)->sin_addr.s_addr)(__uint32_t)(__builtin_constant_p((u_long)((struct sockaddr_in *)sa)->sin_addr.s_addr) ? (__uint32_t)(((__uint32_t)((u_long )((struct sockaddr_in *)sa)->sin_addr.s_addr) & 0xff) << 24 | ((__uint32_t)((u_long)((struct sockaddr_in *)sa)->sin_addr .s_addr) & 0xff00) << 8 | ((__uint32_t)((u_long)((struct sockaddr_in *)sa)->sin_addr.s_addr) & 0xff0000) >> 8 | ((__uint32_t)((u_long)((struct sockaddr_in *)sa)->sin_addr .s_addr) & 0xff000000) >> 24) : __swap32md((u_long) ((struct sockaddr_in *)sa)->sin_addr.s_addr)); |
| 446 | else |
| 447 | machine = 0; |
| 448 | |
| 449 | for (ip = Scores; ip != NULL((void *)0); ip = ip->i_next) |
| 450 | if (ip->i_machine == machine |
| 451 | && ip->i_uid == uid |
| 452 | /* && ip->i_team == team */ |
| 453 | && strncmp(ip->i_name, name, NAMELEN20) == 0) |
| 454 | break; |
| 455 | |
| 456 | if (ip != NULL((void *)0)) { |
| 457 | if (ip->i_team != team) { |
| 458 | logx(LOG_INFO6, "player %s %s team %c", |
| 459 | name, |
| 460 | team == ' ' ? "left" : ip->i_team == ' ' ? |
| 461 | "joined" : "changed to", |
| 462 | team == ' ' ? ip->i_team : team); |
| 463 | ip->i_team = team; |
| 464 | } |
| 465 | if (ip->i_entries < conf_scoredecay) |
| 466 | ip->i_entries++; |
| 467 | else |
| 468 | ip->i_kills = (ip->i_kills * (conf_scoredecay - 1)) |
| 469 | / conf_scoredecay; |
| 470 | ip->i_score = ip->i_kills / (double) ip->i_entries; |
| 471 | } |
| 472 | else { |
| 473 | /* Alloc new entry -- it is released in clear_scores() */ |
| 474 | ip = malloc(sizeof (IDENT)); |
| 475 | if (ip == NULL((void *)0)) { |
| 476 | logit(LOG_ERR3, "malloc"); |
| 477 | /* Fourth down, time to punt */ |
| 478 | ip = &punt; |
| 479 | } |
| 480 | ip->i_machine = machine; |
| 481 | ip->i_team = team; |
| 482 | ip->i_uid = uid; |
| 483 | strlcpy(ip->i_name, name, sizeof ip->i_name); |
| 484 | ip->i_kills = 0; |
| 485 | ip->i_entries = 1; |
| 486 | ip->i_score = 0; |
| 487 | ip->i_absorbed = 0; |
| 488 | ip->i_faced = 0; |
| 489 | ip->i_shot = 0; |
| 490 | ip->i_robbed = 0; |
| 491 | ip->i_slime = 0; |
| 492 | ip->i_missed = 0; |
| 493 | ip->i_ducked = 0; |
| 494 | ip->i_gkills = ip->i_bkills = ip->i_deaths = 0; |
| 495 | ip->i_stillb = ip->i_saved = 0; |
| 496 | ip->i_next = Scores; |
| 497 | Scores = ip; |
| 498 | |
| 499 | logx(LOG_INFO6, "new player: %s%s%c%s", |
| 500 | name, |
| 501 | team == ' ' ? "" : " (team ", |
| 502 | team, |
| 503 | team == ' ' ? "" : ")"); |
| 504 | } |
| 505 | |
| 506 | return ip; |
| 507 | } |
| 508 | |
| 509 | void |
| 510 | answer_info(FILE *fp) |
| 511 | { |
| 512 | struct spawn *sp; |
| 513 | char buf[128]; |
| 514 | const char *bf; |
| 515 | struct sockaddr_in *sa; |
| 516 | |
| 517 | if (Spawn == NULL((void *)0)) |
| 518 | return; |
| 519 | fprintf(fp, "\nSpawning connections:\n"); |
| 520 | for (sp = Spawn; sp; sp = sp->next) { |
| 521 | sa = (struct sockaddr_in *)&sp->source; |
| 522 | bf = inet_ntop(AF_INET2, &sa->sin_addr, buf, sizeof buf); |
| 523 | if (!bf) { |
| 524 | logit(LOG_WARNING4, "inet_ntop"); |
| 525 | bf = "?"; |
| 526 | } |
| 527 | fprintf(fp, "fd %d: state %d, from %s:%d\n", |
| 528 | sp->fd, sp->inlen + (sp->reading_msg ? sp->msglen : 0), |
| 529 | bf, sa->sin_port); |
| 530 | } |
| 531 | } |