1 /* $OpenBSD: score.c,v 1.9 2004/11/29 08:52:29 jsg Exp $ */ 2 /* $NetBSD: score.c,v 1.3 1995/04/22 10:09:12 cgd Exp $ */ 3 4 /* 5 * Copyright (c) 1980, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. 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 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 #ifndef lint 34 #if 0 35 static char sccsid[] = "@(#)score.c 8.1 (Berkeley) 5/31/93"; 36 #else 37 static char rcsid[] = "$OpenBSD: score.c,v 1.9 2004/11/29 08:52:29 jsg Exp $"; 38 #endif 39 #endif /* not lint */ 40 41 #include "robots.h" 42 #include "pathnames.h" 43 44 char *Scorefile = _PATH_SCORE; 45 46 #ifndef MAX_PER_UID 47 #define MAX_PER_UID 5 48 #endif 49 50 int Max_per_uid = MAX_PER_UID; 51 52 static SCORE Top[MAXSCORES]; 53 54 /* 55 * score: 56 * Post the player's score, if reasonable, and then print out the 57 * top list. 58 */ 59 void 60 score(int score_wfd) 61 { 62 int inf = score_wfd; 63 SCORE *scp; 64 uid_t uid; 65 bool done_show = FALSE; 66 static int numscores, max_uid; 67 68 Newscore = FALSE; 69 if (inf < 0) 70 return; 71 72 if (read(inf, &max_uid, sizeof max_uid) == sizeof max_uid) 73 read(inf, Top, sizeof Top); 74 else { 75 for (scp = Top; scp < &Top[MAXSCORES]; scp++) 76 scp->s_score = -1; 77 max_uid = Max_per_uid; 78 } 79 80 uid = getuid(); 81 if (Top[MAXSCORES-1].s_score <= Score) { 82 numscores = 0; 83 for (scp = Top; scp < &Top[MAXSCORES]; scp++) 84 if (scp->s_score < 0 || 85 (scp->s_uid == uid && ++numscores == max_uid)) { 86 if (scp->s_score > Score) 87 break; 88 scp->s_score = Score; 89 scp->s_uid = uid; 90 set_name(scp); 91 Newscore = TRUE; 92 break; 93 } 94 if (scp == &Top[MAXSCORES]) { 95 Top[MAXSCORES-1].s_score = Score; 96 Top[MAXSCORES-1].s_uid = uid; 97 set_name(&Top[MAXSCORES-1]); 98 Newscore = TRUE; 99 } 100 if (Newscore) 101 qsort(Top, MAXSCORES, sizeof Top[0], cmp_sc); 102 } 103 104 if (!Newscore) { 105 Full_clear = FALSE; 106 fsync(inf); 107 lseek(inf, 0, SEEK_SET); 108 return; 109 } 110 else 111 Full_clear = TRUE; 112 113 for (scp = Top; scp < &Top[MAXSCORES]; scp++) { 114 if (scp->s_score < 0) 115 break; 116 move((scp - Top) + 1, 15); 117 if (!done_show && scp->s_uid == uid && scp->s_score == Score) 118 standout(); 119 printw(" %d\t%d\t%-*s ", (scp - Top) + 1, scp->s_score, 120 (int)(sizeof scp->s_name), scp->s_name); 121 if (!done_show && scp->s_uid == uid && scp->s_score == Score) { 122 standend(); 123 done_show = TRUE; 124 } 125 } 126 Num_scores = scp - Top; 127 refresh(); 128 129 if (Newscore) { 130 lseek(inf, 0L, SEEK_SET); 131 write(inf, &max_uid, sizeof max_uid); 132 write(inf, Top, sizeof Top); 133 } 134 fsync(inf); 135 lseek(inf, 0, SEEK_SET); 136 } 137 138 void 139 set_name(SCORE *scp) 140 { 141 PASSWD *pp; 142 143 if ((pp = getpwuid(scp->s_uid)) == NULL) 144 pp->pw_name = "???"; 145 strlcpy(scp->s_name, pp->pw_name, MAXLOGNAME); 146 } 147 148 /* 149 * cmp_sc: 150 * Compare two scores. 151 */ 152 int 153 cmp_sc(const void *s1, const void *s2) 154 { 155 return ((SCORE *)s2)->s_score - ((SCORE *)s1)->s_score; 156 } 157 158 /* 159 * show_score: 160 * Show the score list for the '-s' option. 161 */ 162 void 163 show_score(void) 164 { 165 SCORE *scp; 166 int inf; 167 static int max_score; 168 169 if ((inf = open(Scorefile, O_RDONLY)) < 0) { 170 perror(Scorefile); 171 return; 172 } 173 174 for (scp = Top; scp < &Top[MAXSCORES]; scp++) 175 scp->s_score = -1; 176 177 read(inf, &max_score, sizeof max_score); 178 read(inf, Top, sizeof Top); 179 close(inf); 180 inf = 1; 181 for (scp = Top; scp < &Top[MAXSCORES]; scp++) 182 if (scp->s_score >= 0) 183 printf("%d\t%d\t%.*s\n", inf++, scp->s_score, 184 (int)(sizeof scp->s_name), scp->s_name); 185 } 186