xref: /netbsd-src/games/atc/log.c (revision 4b30c543a0b21e3ba94f2c569e9a82b4fdb2075f)
1 /*-
2  * Copyright (c) 1990 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Ed James.
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. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *	This product includes software developed by the University of
19  *	California, Berkeley and its contributors.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  */
36 
37 /*
38  * Copyright (c) 1987 by Ed James, UC Berkeley.  All rights reserved.
39  *
40  * Copy permission is hereby granted provided that this notice is
41  * retained on all partial or complete copies.
42  *
43  * For more info on this and all of my stuff, mail edjames@berkeley.edu.
44  */
45 
46 #ifndef lint
47 /*static char sccsid[] = "from: @(#)log.c	5.7 (Berkeley) 10/30/90";*/
48 static char rcsid[] = "$Id: log.c,v 1.2 1993/08/01 18:57:06 mycroft Exp $";
49 #endif not lint
50 
51 #include "include.h"
52 #include "pathnames.h"
53 
54 compar(a, b)
55 	SCORE	*a, *b;
56 {
57 	if (b->planes == a->planes)
58 		return (b->time - a->time);
59 	else
60 		return (b->planes - a->planes);
61 }
62 
63 #define SECAMIN		60
64 #define MINAHOUR	60
65 #define HOURADAY	24
66 #define SECAHOUR	(SECAMIN * MINAHOUR)
67 #define SECADAY		(SECAHOUR * HOURADAY)
68 #define DAY(t)		((t) / SECADAY)
69 #define HOUR(t)		(((t) % SECADAY) / SECAHOUR)
70 #define MIN(t)		(((t) % SECAHOUR) / SECAMIN)
71 #define SEC(t)		((t) % SECAMIN)
72 
73 char	*
74 timestr(t)
75 {
76 	static char	s[80];
77 
78 	if (DAY(t) > 0)
79 		(void)sprintf(s, "%dd+%02dhrs", DAY(t), HOUR(t));
80 	else if (HOUR(t) > 0)
81 		(void)sprintf(s, "%d:%02d:%02d", HOUR(t), MIN(t), SEC(t));
82 	else if (MIN(t) > 0)
83 		(void)sprintf(s, "%d:%02d", MIN(t), SEC(t));
84 	else if (SEC(t) > 0)
85 		(void)sprintf(s, ":%02d", SEC(t));
86 	else
87 		*s = '\0';
88 
89 	return (s);
90 }
91 
92 log_score(list_em)
93 {
94 	register int	i, fd, num_scores = 0, good, changed = 0, found = 0;
95 	struct passwd	*pw;
96 	FILE		*fp;
97 	char		*cp, *index(), *rindex();
98 	SCORE		score[100], thisscore;
99 #ifdef SYSV
100 	struct utsname	name;
101 #endif
102 
103 	umask(0);
104 	fd = open(_PATH_SCORE, O_CREAT|O_RDWR, 0644);
105 	if (fd < 0) {
106 		perror(_PATH_SCORE);
107 		return (-1);
108 	}
109 	/*
110 	 * This is done to take advantage of stdio, while still
111 	 * allowing a O_CREAT during the open(2) of the log file.
112 	 */
113 	fp = fdopen(fd, "r+");
114 	if (fp == NULL) {
115 		perror(_PATH_SCORE);
116 		return (-1);
117 	}
118 #ifdef BSD
119 	if (flock(fileno(fp), LOCK_EX) < 0)
120 #endif
121 #ifdef SYSV
122 	while (lockf(fileno(fp), F_LOCK, 1) < 0)
123 #endif
124 	{
125 		perror("flock");
126 		return (-1);
127 	}
128 	for (;;) {
129 		good = fscanf(fp, "%s %s %s %d %d %d",
130 			score[num_scores].name,
131 			score[num_scores].host,
132 			score[num_scores].game,
133 			&score[num_scores].planes,
134 			&score[num_scores].time,
135 			&score[num_scores].real_time);
136 		if (good != 6 || ++num_scores >= NUM_SCORES)
137 			break;
138 	}
139 	if (!test_mode && !list_em) {
140 		if ((pw = (struct passwd *) getpwuid(getuid())) == NULL) {
141 			fprintf(stderr,
142 				"getpwuid failed for uid %d.  Who are you?\n",
143 				getuid());
144 			return (-1);
145 		}
146 		strcpy(thisscore.name, pw->pw_name);
147 #ifdef BSD
148 		if (gethostname(thisscore.host, sizeof (thisscore.host)) < 0) {
149 			perror("gethostname");
150 			return (-1);
151 		}
152 #endif
153 #ifdef SYSV
154 		uname(&name);
155 		strcpy(thisscore.host, name.sysname);
156 #endif
157 
158 		cp = rindex(file, '/');
159 		if (cp == NULL) {
160 			fprintf(stderr, "log: where's the '/' in %s?\n", file);
161 			return (-1);
162 		}
163 		cp++;
164 		strcpy(thisscore.game, cp);
165 
166 		thisscore.time = clck;
167 		thisscore.planes = safe_planes;
168 		thisscore.real_time = time(0) - start_time;
169 
170 		for (i = 0; i < num_scores; i++) {
171 			if (strcmp(thisscore.name, score[i].name) == 0 &&
172 			    strcmp(thisscore.host, score[i].host) == 0 &&
173 			    strcmp(thisscore.game, score[i].game) == 0) {
174 				if (thisscore.time > score[i].time) {
175 					score[i].time = thisscore.time;
176 					score[i].planes = thisscore.planes;
177 					score[i].real_time =
178 						thisscore.real_time;
179 					changed++;
180 				}
181 				found++;
182 				break;
183 			}
184 		}
185 		if (!found) {
186 			for (i = 0; i < num_scores; i++) {
187 				if (thisscore.time > score[i].time) {
188 					if (num_scores < NUM_SCORES)
189 						num_scores++;
190 					bcopy(&score[i],
191 						&score[num_scores - 1],
192 						sizeof (score[i]));
193 					bcopy(&thisscore, &score[i],
194 						sizeof (score[i]));
195 					changed++;
196 					break;
197 				}
198 			}
199 		}
200 		if (!found && !changed && num_scores < NUM_SCORES) {
201 			bcopy(&thisscore, &score[num_scores],
202 				sizeof (score[num_scores]));
203 			num_scores++;
204 			changed++;
205 		}
206 
207 		if (changed) {
208 			if (found)
209 				puts("You beat your previous score!");
210 			else
211 				puts("You made the top players list!");
212 			qsort(score, num_scores, sizeof (*score), compar);
213 			rewind(fp);
214 			for (i = 0; i < num_scores; i++)
215 				fprintf(fp, "%s %s %s %d %d %d\n",
216 					score[i].name, score[i].host,
217 					score[i].game, score[i].planes,
218 					score[i].time, score[i].real_time);
219 		} else {
220 			if (found)
221 				puts("You didn't beat your previous score.");
222 			else
223 				puts("You didn't make the top players list.");
224 		}
225 		putchar('\n');
226 	}
227 #ifdef BSD
228 	flock(fileno(fp), LOCK_UN);
229 #endif
230 #ifdef SYSV
231 	/* lock will evaporate upon close */
232 #endif
233 	fclose(fp);
234 	printf("%2s:  %-8s  %-8s  %-18s  %4s  %9s  %4s\n", "#", "name", "host",
235 		"game", "time", "real time", "planes safe");
236 	puts("-------------------------------------------------------------------------------");
237 	for (i = 0; i < num_scores; i++) {
238 		cp = index(score[i].host, '.');
239 		if (cp != NULL)
240 			*cp = '\0';
241 		printf("%2d:  %-8s  %-8s  %-18s  %4d  %9s  %4d\n", i + 1,
242 			score[i].name, score[i].host, score[i].game,
243 			score[i].time, timestr(score[i].real_time),
244 			score[i].planes);
245 	}
246 	putchar('\n');
247 	return (0);
248 }
249