score.c revision 1.11
1/*	$OpenBSD: score.c,v 1.11 2014/11/16 04:49:48 guenther 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#include	"robots.h"
34#include	"pathnames.h"
35
36char	*Scorefile = _PATH_SCORE;
37
38#ifndef MAX_PER_UID
39#define MAX_PER_UID	5
40#endif
41
42int	Max_per_uid = MAX_PER_UID;
43
44static SCORE	Top[MAXSCORES];
45
46/*
47 * score:
48 *	Post the player's score, if reasonable, and then print out the
49 *	top list.
50 */
51void
52score(int score_wfd)
53{
54	int	inf = score_wfd;
55	SCORE	*scp;
56	uid_t	uid;
57	bool	done_show = FALSE;
58	static int	numscores, max_uid;
59
60	Newscore = FALSE;
61	if (inf < 0)
62		return;
63
64	if (read(inf, &max_uid, sizeof max_uid) == sizeof max_uid)
65		read(inf, Top, sizeof Top);
66	else {
67		for (scp = Top; scp < &Top[MAXSCORES]; scp++)
68			scp->s_score = -1;
69		max_uid = Max_per_uid;
70	}
71
72	uid = getuid();
73	if (Top[MAXSCORES-1].s_score <= Score) {
74		numscores = 0;
75		for (scp = Top; scp < &Top[MAXSCORES]; scp++)
76			if (scp->s_score < 0 ||
77			    (scp->s_uid == uid && ++numscores == max_uid)) {
78				if (scp->s_score > Score)
79					break;
80				scp->s_score = Score;
81				scp->s_uid = uid;
82				set_name(scp);
83				Newscore = TRUE;
84				break;
85			}
86		if (scp == &Top[MAXSCORES]) {
87			Top[MAXSCORES-1].s_score = Score;
88			Top[MAXSCORES-1].s_uid = uid;
89			set_name(&Top[MAXSCORES-1]);
90			Newscore = TRUE;
91		}
92		if (Newscore)
93			qsort(Top, MAXSCORES, sizeof Top[0], cmp_sc);
94	}
95
96	if (!Newscore) {
97		Full_clear = FALSE;
98		fsync(inf);
99		lseek(inf, 0, SEEK_SET);
100		return;
101	}
102	else
103		Full_clear = TRUE;
104
105	for (scp = Top; scp < &Top[MAXSCORES]; scp++) {
106		if (scp->s_score < 0)
107			break;
108		move((scp - Top) + 1, 15);
109		if (!done_show && scp->s_uid == uid && scp->s_score == Score)
110			standout();
111		printw(" %d\t%d\t%-*s ", (scp - Top) + 1, scp->s_score,
112			(int)(sizeof scp->s_name), scp->s_name);
113		if (!done_show && scp->s_uid == uid && scp->s_score == Score) {
114			standend();
115			done_show = TRUE;
116		}
117	}
118	Num_scores = scp - Top;
119	refresh();
120
121	if (Newscore) {
122		lseek(inf, 0L, SEEK_SET);
123		write(inf, &max_uid, sizeof max_uid);
124		write(inf, Top, sizeof Top);
125	}
126	fsync(inf);
127	lseek(inf, 0, SEEK_SET);
128}
129
130void
131set_name(SCORE *scp)
132{
133	PASSWD	*pp;
134
135	if ((pp = getpwuid(scp->s_uid)) == NULL)
136		pp->pw_name = "???";
137	strlcpy(scp->s_name, pp->pw_name, LOGIN_NAME_MAX);
138}
139
140/*
141 * cmp_sc:
142 *	Compare two scores.
143 */
144int
145cmp_sc(const void *s1, const void *s2)
146{
147	return ((SCORE *)s2)->s_score - ((SCORE *)s1)->s_score;
148}
149
150/*
151 * show_score:
152 *	Show the score list for the '-s' option.
153 */
154void
155show_score(void)
156{
157	SCORE	*scp;
158	int	inf;
159	static int	max_score;
160
161	if ((inf = open(Scorefile, O_RDONLY)) < 0) {
162		perror(Scorefile);
163		return;
164	}
165
166	for (scp = Top; scp < &Top[MAXSCORES]; scp++)
167		scp->s_score = -1;
168
169	read(inf, &max_score, sizeof max_score);
170	read(inf, Top, sizeof Top);
171	close(inf);
172	inf = 1;
173	for (scp = Top; scp < &Top[MAXSCORES]; scp++)
174		if (scp->s_score >= 0)
175			printf("%d\t%d\t%.*s\n", inf++, scp->s_score,
176				(int)(sizeof scp->s_name), scp->s_name);
177}
178