Mercurial > emacs
annotate lib-src/update-game-score.c @ 44464:ca04149c39a4
cvs-mode-add does not ask for a description any more.
author | Stefan Monnier <monnier@iro.umontreal.ca> |
---|---|
date | Tue, 09 Apr 2002 18:41:56 +0000 |
parents | 16b3622178f9 |
children | a0dc261f564a |
rev | line source |
---|---|
44184 | 1 /* update-game-score.c --- Update a score file |
2 Copyright (C) 2002 Free Software Foundation, Inc. | |
3 | |
4 This file is part of GNU Emacs. | |
5 | |
6 GNU Emacs is free software; you can redistribute it and/or modify | |
7 it under the terms of the GNU General Public License as published by | |
8 the Free Software Foundation; either version 2, or (at your option) | |
9 any later version. | |
10 | |
11 GNU Emacs is distributed in the hope that it will be useful, | |
12 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 GNU General Public License for more details. | |
15 | |
16 You should have received a copy of the GNU General Public License | |
17 along with GNU Emacs; see the file COPYING. If not, write to | |
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
19 Boston, MA 02111-1307, USA. */ | |
20 | |
21 /* This program is allows a game to securely and atomically update a | |
22 score file. It should be installed setgid, owned by an appropriate | |
23 group like `games'. | |
24 | |
25 Created 2002/03/22, by Colin Walters <walters@debian.org> | |
26 */ | |
27 | |
28 #define _GNU_SOURCE | |
29 | |
30 #include <unistd.h> | |
31 #include <errno.h> | |
32 #include <string.h> | |
33 #include <stdlib.h> | |
34 #include <stdio.h> | |
35 #include <time.h> | |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
36 #include <pwd.h> |
44184 | 37 #include <ctype.h> |
38 #include <fcntl.h> | |
39 #include <sys/stat.h> | |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
40 #include <config.h> |
44184 | 41 |
42 #define MAX_ATTEMPTS 5 | |
44419
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
43 |
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
44 #ifdef HAVE_SHARED_GAME_DIR |
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
45 #define SCORE_FILE_PREFIX HAVE_SHARED_GAME_DIR |
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
46 #else |
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
47 #define SCORE_FILE_PREFIX "$HOME" |
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
48 #endif |
44184 | 49 |
50 int | |
51 usage(int err) | |
52 { | |
53 fprintf(stdout, "Usage: update-game-score [-m MAX ] [ -r ] game/scorefile SCORE DATA\n"); | |
54 fprintf(stdout, " update-game-score -h\n"); | |
55 fprintf(stdout, " -h\t\tDisplay this help.\n"); | |
56 fprintf(stdout, " -m MAX\t\tLimit the maximum number of scores to MAX.\n"); | |
57 fprintf(stdout, " -r\t\tSort the scores in increasing order.\n"); | |
58 exit(err); | |
59 } | |
60 | |
61 int | |
62 lock_file(const char *filename, void **state); | |
63 int | |
64 unlock_file(const char *filename, void *state); | |
65 | |
66 struct score_entry | |
67 { | |
68 long score; | |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
69 char *username; |
44184 | 70 char *data; |
71 }; | |
72 | |
73 int | |
74 read_scores(const char *filename, struct score_entry **scores, | |
75 int *count); | |
76 int | |
77 push_score(struct score_entry **scores, int *count, | |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
78 int newscore, char *username, char *newdata); |
44184 | 79 void |
80 sort_scores(struct score_entry *scores, int count, int reverse); | |
81 int | |
82 write_scores(const char *filename, const struct score_entry *scores, | |
83 int count); | |
84 | |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
85 char * |
44419
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
86 get_user_id(struct passwd *buf) |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
87 { |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
88 char *name; |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
89 if (!buf) |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
90 { |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
91 int count = 1; |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
92 int uid = (int) getuid(); |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
93 while (uid /= 10) |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
94 count++; |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
95 name = malloc(count+1); |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
96 sprintf(name, "%d", uid); |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
97 return name; |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
98 } |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
99 return buf->pw_name; |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
100 } |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
101 |
44419
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
102 char * |
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
103 get_home_dir(struct passwd *buf) |
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
104 { |
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
105 if (!buf) |
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
106 return NULL; |
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
107 return buf->pw_dir; |
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
108 } |
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
109 |
44184 | 110 int |
111 main(int argc, char **argv) | |
112 { | |
113 int c; | |
114 void *lockstate; | |
44419
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
115 char *scorefile, *prefix; |
44184 | 116 struct stat buf; |
117 struct score_entry *scores; | |
118 int newscore, scorecount, reverse = 0, max = -1; | |
119 char *newdata; | |
44419
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
120 struct passwd *passwdbuf; |
44184 | 121 |
122 srand(time(0)); | |
123 | |
124 while ((c = getopt(argc, argv, "hrm:")) != -1) | |
125 switch (c) | |
126 { | |
127 case 'h': | |
128 usage(0); | |
129 break; | |
130 case 'r': | |
131 reverse = 1; | |
132 break; | |
133 case 'm': | |
134 max = atoi(optarg); | |
135 break; | |
136 default: | |
137 usage(1); | |
138 } | |
139 | |
140 if (optind+3 != argc) | |
141 usage(1); | |
44419
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
142 |
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
143 passwdbuf = getpwuid(getuid()); |
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
144 |
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
145 if (!strcmp(SCORE_FILE_PREFIX, "$HOME")) |
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
146 { |
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
147 prefix = get_home_dir(passwdbuf); |
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
148 if (!prefix) |
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
149 { |
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
150 fprintf(stderr, "Unable to determine home directory\n"); |
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
151 exit(1); |
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
152 } |
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
153 } |
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
154 else |
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
155 prefix = SCORE_FILE_PREFIX; |
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
156 |
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
157 scorefile = malloc(strlen(prefix) + strlen(argv[optind]) + 1); |
44184 | 158 if (!scorefile) |
159 { | |
160 fprintf(stderr, "Couldn't create score file name: %s\n", | |
161 strerror(errno)); | |
162 goto fail; | |
163 } | |
44419
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
164 strcpy(scorefile, prefix); |
44184 | 165 strcat(scorefile, argv[optind]); |
166 newscore = atoi(argv[optind+1]); | |
167 newdata = argv[optind+2]; | |
168 | |
169 if (stat(scorefile, &buf) < 0) | |
170 { | |
171 fprintf(stderr, "Failed to access scores file \"%s\": %s\n", | |
172 scorefile, strerror(errno)); | |
173 goto fail; | |
174 } | |
175 if (lock_file(scorefile, &lockstate) < 0) | |
176 { | |
177 fprintf(stderr, "Failed to lock scores file \"%s\": %s\n", | |
178 scorefile, strerror(errno)); | |
179 goto fail; | |
180 } | |
181 if (read_scores(scorefile, &scores, &scorecount) < 0) | |
182 { | |
183 fprintf(stderr, "Failed to read scores file \"%s\": %s\n", | |
184 scorefile, strerror(errno)); | |
185 goto fail_unlock; | |
186 } | |
44419
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
187 push_score(&scores, &scorecount, newscore, get_user_id(passwdbuf), newdata); |
44184 | 188 sort_scores(scores, scorecount, reverse); |
189 if (write_scores(scorefile, scores, scorecount) < 0) | |
190 { | |
191 fprintf(stderr, "Failed to write scores file \"%s\": %s\n", | |
192 scorefile, strerror(errno)); | |
193 goto fail_unlock; | |
194 } | |
195 unlock_file(scorefile, lockstate); | |
196 exit(0); | |
197 fail_unlock: | |
198 unlock_file(scorefile, lockstate); | |
199 fail: | |
200 exit(1); | |
201 } | |
202 | |
203 int | |
204 read_score(FILE *f, struct score_entry *score) | |
205 { | |
206 int c; | |
207 if (feof(f)) | |
208 return 1; | |
209 while ((c = getc(f)) != EOF | |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
210 && isdigit(c)) |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
211 { |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
212 score->score *= 10; |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
213 score->score += (c-48); |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
214 } |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
215 while ((c = getc(f)) != EOF |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
216 && isspace(c)) |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
217 ; |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
218 if (c == EOF) |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
219 return -1; |
44404
21e4d76a9e8a
Actually make previous changes work (oops).
Colin Walters <walters@gnu.org>
parents:
44402
diff
changeset
|
220 ungetc(c, f); |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
221 #ifdef HAVE_GETDELIM |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
222 { |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
223 int count = 0; |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
224 if (getdelim(&score->username, &count, ' ', f) < 1 |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
225 || score->username == NULL) |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
226 return -1; |
44184 | 227 } |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
228 #else |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
229 { |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
230 int unameread = 0; |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
231 int unamelen = 30; |
44404
21e4d76a9e8a
Actually make previous changes work (oops).
Colin Walters <walters@gnu.org>
parents:
44402
diff
changeset
|
232 char *username = malloc(unamelen); |
21e4d76a9e8a
Actually make previous changes work (oops).
Colin Walters <walters@gnu.org>
parents:
44402
diff
changeset
|
233 if (!username) |
21e4d76a9e8a
Actually make previous changes work (oops).
Colin Walters <walters@gnu.org>
parents:
44402
diff
changeset
|
234 return -1; |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
235 |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
236 while ((c = getc(f)) != EOF |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
237 && !isspace(c)) |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
238 { |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
239 if (unameread == unamelen) |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
240 { |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
241 if (!(username = realloc(username, unamelen *= 2))) |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
242 return -1; |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
243 } |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
244 username[unameread] = c; |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
245 unameread++; |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
246 } |
44404
21e4d76a9e8a
Actually make previous changes work (oops).
Colin Walters <walters@gnu.org>
parents:
44402
diff
changeset
|
247 if (c == EOF) |
21e4d76a9e8a
Actually make previous changes work (oops).
Colin Walters <walters@gnu.org>
parents:
44402
diff
changeset
|
248 return -1; |
21e4d76a9e8a
Actually make previous changes work (oops).
Colin Walters <walters@gnu.org>
parents:
44402
diff
changeset
|
249 username[unameread] = '\0'; |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
250 score->username = username; |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
251 } |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
252 #endif |
44184 | 253 #ifdef HAVE_GETLINE |
254 score->data = NULL; | |
255 errno = ESUCCES; | |
256 { | |
257 int len; | |
258 if (getline(&score->data, &len, f) < 0) | |
259 return -1; | |
44419
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
260 score->data[strlen(score->data)-1] = '\0'; |
44184 | 261 } |
262 #else | |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
263 { |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
264 int cur = 0; |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
265 int len = 16; |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
266 char *buf = malloc(len); |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
267 if (!buf) |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
268 return -1; |
44404
21e4d76a9e8a
Actually make previous changes work (oops).
Colin Walters <walters@gnu.org>
parents:
44402
diff
changeset
|
269 while ((c = getc(f)) != EOF |
21e4d76a9e8a
Actually make previous changes work (oops).
Colin Walters <walters@gnu.org>
parents:
44402
diff
changeset
|
270 && c != '\n') |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
271 { |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
272 if (cur >= len-1) |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
273 { |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
274 if (!(buf = realloc(buf, len *= 2))) |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
275 return -1; |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
276 } |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
277 buf[cur] = c; |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
278 cur++; |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
279 } |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
280 score->data = buf; |
44419
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
281 score->data[cur] = '\0'; |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
282 } |
44184 | 283 #endif |
284 return 0; | |
285 } | |
286 | |
287 int | |
288 read_scores(const char *filename, struct score_entry **scores, | |
289 int *count) | |
290 { | |
291 int readval, scorecount, cursize; | |
292 struct score_entry *ret; | |
293 FILE *f = fopen(filename, "r"); | |
294 if (!f) | |
295 return -1; | |
296 scorecount = 0; | |
297 cursize = 16; | |
298 ret = malloc(sizeof(struct score_entry) * cursize); | |
299 if (!ret) | |
300 return -1; | |
301 while ((readval = read_score(f, &ret[scorecount])) == 0) | |
302 { | |
303 /* We encoutered an error */ | |
304 if (readval < 0) | |
305 return -1; | |
306 scorecount++; | |
307 if (scorecount >= cursize) | |
308 { | |
309 ret = realloc(ret, cursize *= 2); | |
310 if (!ret) | |
311 return -1; | |
312 } | |
313 } | |
314 *count = scorecount; | |
315 *scores = ret; | |
316 return 0; | |
317 } | |
318 | |
319 int | |
320 score_compare(const void *a, const void *b) | |
321 { | |
322 const struct score_entry *sa = (const struct score_entry *) a; | |
323 const struct score_entry *sb = (const struct score_entry *) b; | |
324 return (sb->score > sa->score) - (sb->score < sa->score); | |
325 } | |
326 | |
327 int | |
328 score_compare_reverse(const void *a, const void *b) | |
329 { | |
330 const struct score_entry *sa = (const struct score_entry *) a; | |
331 const struct score_entry *sb = (const struct score_entry *) b; | |
332 return (sa->score > sb->score) - (sa->score < sb->score); | |
333 } | |
334 | |
335 int | |
336 push_score(struct score_entry **scores, int *count, | |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
337 int newscore, char *username, char *newdata) |
44184 | 338 { |
339 struct score_entry *newscores = realloc(*scores, | |
340 sizeof(struct score_entry) * ((*count) + 1)); | |
341 if (!newscores) | |
342 return -1; | |
343 newscores[*count].score = newscore; | |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
344 newscores[*count].username = username; |
44184 | 345 newscores[*count].data = newdata; |
346 (*count) += 1; | |
347 *scores = newscores; | |
348 return 0; | |
349 } | |
350 | |
351 void | |
352 sort_scores(struct score_entry *scores, int count, int reverse) | |
353 { | |
354 qsort(scores, count, sizeof(struct score_entry), | |
355 reverse ? score_compare_reverse : score_compare); | |
356 } | |
357 | |
358 int | |
359 write_scores(const char *filename, const struct score_entry *scores, | |
360 int count) | |
361 { | |
362 FILE *f; | |
363 int i; | |
364 char *tempfile = malloc(strlen(filename) + strlen(".tempXXXXXX") + 1); | |
365 if (!tempfile) | |
366 return -1; | |
367 strcpy(tempfile, filename); | |
368 strcat(tempfile, ".tempXXXXXX"); | |
369 if (mkstemp(tempfile) < 0 | |
370 || !(f = fopen(tempfile, "w"))) | |
371 return -1; | |
372 for (i = 0; i < count; i++) | |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
373 if (fprintf(f, "%ld %s %s\n", scores[i].score, scores[i].username, |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
374 scores[i].data) < 0) |
44184 | 375 return -1; |
376 fclose(f); | |
377 rename(tempfile, filename); | |
378 return 0; | |
379 } | |
380 | |
381 #if 0 | |
382 int | |
383 lock_file(const char *filename, void **state) | |
384 { | |
385 struct flock lock; | |
386 int *istate; | |
387 int fd, attempts = 0, ret = 0; | |
388 lock.l_type = F_WRLCK; | |
389 lock.l_whence = SEEK_SET; | |
390 lock.l_start = 0; | |
391 lock.l_len = 0; | |
392 istate = malloc(sizeof(int)); | |
393 if (!istate) | |
394 return -1; | |
395 if ((fd = open(filename, O_RDWR, 0600)) < 0) | |
396 return -1; | |
397 *istate = fd; | |
398 trylock: | |
399 attempts++; | |
400 if ((ret = fcntl(fd, F_GETLK, &lock)) == -1) | |
401 { | |
402 if (ret == EACCES || ret == EAGAIN) | |
403 if (attempts > MAX_ATTEMPTS) | |
404 exit(1); | |
405 else | |
406 { | |
407 sleep((rand() % 3)+1); | |
408 goto trylock; | |
409 } | |
410 else | |
411 ret = 0 ; | |
412 } | |
413 else | |
414 ret = 0; | |
415 *state = istate; | |
416 return ret; | |
417 } | |
418 | |
419 int | |
420 unlock_file(const char *filename, void *state) | |
421 { | |
422 int fd, ret; | |
423 fd = *((int *) state); | |
424 free(state); | |
425 ret = close(fd); | |
426 return ret; | |
427 } | |
428 | |
429 #else | |
430 | |
431 int | |
432 lock_file(const char *filename, void **state) | |
433 { | |
434 int fd; | |
435 int attempts = 0; | |
436 char *lockext = ".lockfile"; | |
437 char *lockpath = malloc(strlen(filename) + strlen(lockext) + 60); | |
438 if (!lockpath) | |
439 return -1; | |
440 strcpy(lockpath, filename); | |
441 strcat(lockpath, lockext); | |
442 *state = lockpath; | |
443 trylock: | |
444 attempts++; | |
445 if ((fd = open(lockpath, O_CREAT | O_EXCL, 0600)) < 0) | |
446 { | |
447 if (errno == EEXIST) | |
448 { | |
449 /* Break the lock; we won't corrupt the file, but we might | |
450 lose some scores. */ | |
451 if (attempts > MAX_ATTEMPTS) | |
452 unlink(lockpath); | |
453 else | |
454 sleep((rand() % 2)+1); | |
455 goto trylock; | |
456 } | |
457 else | |
458 return -1; | |
459 } | |
460 close(fd); | |
461 return 0; | |
462 } | |
463 | |
464 int | |
465 unlock_file(const char *filename, void *state) | |
466 { | |
467 char *lockpath = (char *) state; | |
468 int ret = unlink(lockpath); | |
469 int saved_errno = errno; | |
470 free(lockpath); | |
471 errno = saved_errno; | |
472 return ret; | |
473 } | |
474 | |
475 #endif |