1*aa41ab08Stb /* $OpenBSD: score.c,v 1.17 2023/10/10 09:48:06 tb Exp $ */
2df930be7Sderaadt /* $NetBSD: score.c,v 1.3 1995/04/22 10:09:12 cgd Exp $ */
3df930be7Sderaadt
4df930be7Sderaadt /*
5df930be7Sderaadt * Copyright (c) 1980, 1993
6df930be7Sderaadt * The Regents of the University of California. All rights reserved.
7df930be7Sderaadt *
8df930be7Sderaadt * Redistribution and use in source and binary forms, with or without
9df930be7Sderaadt * modification, are permitted provided that the following conditions
10df930be7Sderaadt * are met:
11df930be7Sderaadt * 1. Redistributions of source code must retain the above copyright
12df930be7Sderaadt * notice, this list of conditions and the following disclaimer.
13df930be7Sderaadt * 2. Redistributions in binary form must reproduce the above copyright
14df930be7Sderaadt * notice, this list of conditions and the following disclaimer in the
15df930be7Sderaadt * documentation and/or other materials provided with the distribution.
167a09557bSmillert * 3. Neither the name of the University nor the names of its contributors
17df930be7Sderaadt * may be used to endorse or promote products derived from this software
18df930be7Sderaadt * without specific prior written permission.
19df930be7Sderaadt *
20df930be7Sderaadt * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21df930be7Sderaadt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22df930be7Sderaadt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23df930be7Sderaadt * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24df930be7Sderaadt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25df930be7Sderaadt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26df930be7Sderaadt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27df930be7Sderaadt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28df930be7Sderaadt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29df930be7Sderaadt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30df930be7Sderaadt * SUCH DAMAGE.
31df930be7Sderaadt */
32df930be7Sderaadt
332010f3c8Smestre #include <fcntl.h>
342010f3c8Smestre #include <stdlib.h>
352010f3c8Smestre #include <string.h>
362010f3c8Smestre #include <unistd.h>
372010f3c8Smestre
38df930be7Sderaadt #include "robots.h"
39df930be7Sderaadt
40e224588fStb char Scorefile[PATH_MAX];
41df930be7Sderaadt
42d648d61bSpjanzen #ifndef MAX_PER_UID
43d648d61bSpjanzen #define MAX_PER_UID 5
44d648d61bSpjanzen #endif
45d648d61bSpjanzen
46df930be7Sderaadt int Max_per_uid = MAX_PER_UID;
47df930be7Sderaadt
48df930be7Sderaadt static SCORE Top[MAXSCORES];
49df930be7Sderaadt
50df930be7Sderaadt /*
51df930be7Sderaadt * score:
52df930be7Sderaadt * Post the player's score, if reasonable, and then print out the
53df930be7Sderaadt * top list.
54df930be7Sderaadt */
55d648d61bSpjanzen void
score(int score_wfd)563eb8c9edSjsg score(int score_wfd)
57df930be7Sderaadt {
5897419aa0Spjanzen int inf = score_wfd;
5997419aa0Spjanzen SCORE *scp;
60d648d61bSpjanzen uid_t uid;
6197419aa0Spjanzen bool done_show = FALSE;
62df930be7Sderaadt static int numscores, max_uid;
63df930be7Sderaadt
64df930be7Sderaadt Newscore = FALSE;
65fdb7e56cSpjanzen if (inf < 0)
66fdb7e56cSpjanzen return;
67df930be7Sderaadt
68df930be7Sderaadt if (read(inf, &max_uid, sizeof max_uid) == sizeof max_uid)
69df930be7Sderaadt read(inf, Top, sizeof Top);
70df930be7Sderaadt else {
71df930be7Sderaadt for (scp = Top; scp < &Top[MAXSCORES]; scp++)
72df930be7Sderaadt scp->s_score = -1;
73df930be7Sderaadt max_uid = Max_per_uid;
74df930be7Sderaadt }
75df930be7Sderaadt
76df930be7Sderaadt uid = getuid();
77df930be7Sderaadt if (Top[MAXSCORES-1].s_score <= Score) {
78df930be7Sderaadt numscores = 0;
79df930be7Sderaadt for (scp = Top; scp < &Top[MAXSCORES]; scp++)
80df930be7Sderaadt if (scp->s_score < 0 ||
81df930be7Sderaadt (scp->s_uid == uid && ++numscores == max_uid)) {
82df930be7Sderaadt if (scp->s_score > Score)
83df930be7Sderaadt break;
84df930be7Sderaadt scp->s_score = Score;
85df930be7Sderaadt scp->s_uid = uid;
86df930be7Sderaadt set_name(scp);
87df930be7Sderaadt Newscore = TRUE;
88df930be7Sderaadt break;
89df930be7Sderaadt }
90df930be7Sderaadt if (scp == &Top[MAXSCORES]) {
91df930be7Sderaadt Top[MAXSCORES-1].s_score = Score;
92df930be7Sderaadt Top[MAXSCORES-1].s_uid = uid;
93df930be7Sderaadt set_name(&Top[MAXSCORES-1]);
94df930be7Sderaadt Newscore = TRUE;
95df930be7Sderaadt }
96df930be7Sderaadt if (Newscore)
97df930be7Sderaadt qsort(Top, MAXSCORES, sizeof Top[0], cmp_sc);
98df930be7Sderaadt }
99df930be7Sderaadt
100df930be7Sderaadt if (!Newscore) {
101df930be7Sderaadt Full_clear = FALSE;
1025f463f57Skstailey fsync(inf);
103d648d61bSpjanzen lseek(inf, 0, SEEK_SET);
104df930be7Sderaadt return;
105df930be7Sderaadt }
106df930be7Sderaadt else
107df930be7Sderaadt Full_clear = TRUE;
108df930be7Sderaadt
109df930be7Sderaadt for (scp = Top; scp < &Top[MAXSCORES]; scp++) {
110df930be7Sderaadt if (scp->s_score < 0)
111df930be7Sderaadt break;
1121755eb3fStedu move((scp - Top) + 1, 6);
113df930be7Sderaadt if (!done_show && scp->s_uid == uid && scp->s_score == Score)
114df930be7Sderaadt standout();
115*aa41ab08Stb printw(" %td\t%d\t%-*s ", (scp - Top) + 1, scp->s_score,
116d648d61bSpjanzen (int)(sizeof scp->s_name), scp->s_name);
117df930be7Sderaadt if (!done_show && scp->s_uid == uid && scp->s_score == Score) {
118df930be7Sderaadt standend();
119df930be7Sderaadt done_show = TRUE;
120df930be7Sderaadt }
121df930be7Sderaadt }
122df930be7Sderaadt Num_scores = scp - Top;
123df930be7Sderaadt refresh();
124df930be7Sderaadt
125df930be7Sderaadt if (Newscore) {
126d648d61bSpjanzen lseek(inf, 0L, SEEK_SET);
127df930be7Sderaadt write(inf, &max_uid, sizeof max_uid);
128df930be7Sderaadt write(inf, Top, sizeof Top);
129df930be7Sderaadt }
1305f463f57Skstailey fsync(inf);
131d648d61bSpjanzen lseek(inf, 0, SEEK_SET);
132df930be7Sderaadt }
133df930be7Sderaadt
134d648d61bSpjanzen void
set_name(SCORE * scp)1353eb8c9edSjsg set_name(SCORE *scp)
136df930be7Sderaadt {
13787b7d5d4Stb const char *name;
138df930be7Sderaadt
13987b7d5d4Stb name = getenv("LOGNAME");
14087b7d5d4Stb if (name == NULL || *name == '\0')
14187b7d5d4Stb name = getenv("USER");
14287b7d5d4Stb if (name == NULL || *name == '\0')
14387b7d5d4Stb name = getlogin();
14487b7d5d4Stb if (name == NULL || *name == '\0')
14587b7d5d4Stb name = " ???";
14687b7d5d4Stb
14787b7d5d4Stb strlcpy(scp->s_name, name, LOGIN_NAME_MAX);
148df930be7Sderaadt }
149df930be7Sderaadt
150df930be7Sderaadt /*
151df930be7Sderaadt * cmp_sc:
152df930be7Sderaadt * Compare two scores.
153df930be7Sderaadt */
154d648d61bSpjanzen int
cmp_sc(const void * s1,const void * s2)1553eb8c9edSjsg cmp_sc(const void *s1, const void *s2)
156df930be7Sderaadt {
157d648d61bSpjanzen return ((SCORE *)s2)->s_score - ((SCORE *)s1)->s_score;
158df930be7Sderaadt }
159df930be7Sderaadt
160df930be7Sderaadt /*
161df930be7Sderaadt * show_score:
162df930be7Sderaadt * Show the score list for the '-s' option.
163df930be7Sderaadt */
164d648d61bSpjanzen void
show_score(void)1653eb8c9edSjsg show_score(void)
166df930be7Sderaadt {
16797419aa0Spjanzen SCORE *scp;
16897419aa0Spjanzen int inf;
169df930be7Sderaadt static int max_score;
170df930be7Sderaadt
171df69c215Sderaadt if ((inf = open(Scorefile, O_RDONLY)) == -1) {
172df930be7Sderaadt perror(Scorefile);
173df930be7Sderaadt return;
174df930be7Sderaadt }
175df930be7Sderaadt
176df930be7Sderaadt for (scp = Top; scp < &Top[MAXSCORES]; scp++)
177df930be7Sderaadt scp->s_score = -1;
178df930be7Sderaadt
179df930be7Sderaadt read(inf, &max_score, sizeof max_score);
180df930be7Sderaadt read(inf, Top, sizeof Top);
181df930be7Sderaadt close(inf);
182df930be7Sderaadt inf = 1;
183df930be7Sderaadt for (scp = Top; scp < &Top[MAXSCORES]; scp++)
184df930be7Sderaadt if (scp->s_score >= 0)
185d648d61bSpjanzen printf("%d\t%d\t%.*s\n", inf++, scp->s_score,
186d648d61bSpjanzen (int)(sizeof scp->s_name), scp->s_name);
187df930be7Sderaadt }
188