Mercurial > emacs
annotate lib-src/update-game-score.c @ 48792:a3c07e71f333
*** empty log message ***
author | Steven Tamm <steventamm@mac.com> |
---|---|
date | Tue, 10 Dec 2002 17:58:24 +0000 |
parents | 2346caa2a66a |
children | a29fefe5c6a9 |
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 | |
44481
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
22 score file. It should be installed setuid, owned by an appropriate |
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
23 user like `games'. |
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
24 |
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
25 Alternatively, it can be compiled without HAVE_SHARED_GAME_DIR |
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
26 defined, and in that case it will store scores in the user's home |
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
27 directory (it should NOT be setuid). |
44184 | 28 |
29 Created 2002/03/22, by Colin Walters <walters@debian.org> | |
30 */ | |
31 | |
44639
44995332ed1b
Move config.h before the other headers, to prevent compiler warnings
Eli Zaretskii <eliz@gnu.org>
parents:
44576
diff
changeset
|
32 #include <config.h> |
44995332ed1b
Move config.h before the other headers, to prevent compiler warnings
Eli Zaretskii <eliz@gnu.org>
parents:
44576
diff
changeset
|
33 |
48422
2346caa2a66a
Include unistd.h, string.h, stdlib.h,
Dave Love <fx@gnu.org>
parents:
46774
diff
changeset
|
34 #ifdef HAVE_UNISTD_H |
44184 | 35 #include <unistd.h> |
48422
2346caa2a66a
Include unistd.h, string.h, stdlib.h,
Dave Love <fx@gnu.org>
parents:
46774
diff
changeset
|
36 #endif |
44184 | 37 #include <errno.h> |
48422
2346caa2a66a
Include unistd.h, string.h, stdlib.h,
Dave Love <fx@gnu.org>
parents:
46774
diff
changeset
|
38 #ifdef HAVE_STRING_H |
44184 | 39 #include <string.h> |
48422
2346caa2a66a
Include unistd.h, string.h, stdlib.h,
Dave Love <fx@gnu.org>
parents:
46774
diff
changeset
|
40 #endif |
2346caa2a66a
Include unistd.h, string.h, stdlib.h,
Dave Love <fx@gnu.org>
parents:
46774
diff
changeset
|
41 #ifdef HAVE_STDLIB_H |
44184 | 42 #include <stdlib.h> |
48422
2346caa2a66a
Include unistd.h, string.h, stdlib.h,
Dave Love <fx@gnu.org>
parents:
46774
diff
changeset
|
43 #endif |
44184 | 44 #include <stdio.h> |
45 #include <time.h> | |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
46 #include <pwd.h> |
44184 | 47 #include <ctype.h> |
48422
2346caa2a66a
Include unistd.h, string.h, stdlib.h,
Dave Love <fx@gnu.org>
parents:
46774
diff
changeset
|
48 #ifdef HAVE_FCNTL_H |
44184 | 49 #include <fcntl.h> |
48422
2346caa2a66a
Include unistd.h, string.h, stdlib.h,
Dave Love <fx@gnu.org>
parents:
46774
diff
changeset
|
50 #endif |
2346caa2a66a
Include unistd.h, string.h, stdlib.h,
Dave Love <fx@gnu.org>
parents:
46774
diff
changeset
|
51 #ifdef STDC_HEADERS |
44481
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
52 #include <stdarg.h> |
48422
2346caa2a66a
Include unistd.h, string.h, stdlib.h,
Dave Love <fx@gnu.org>
parents:
46774
diff
changeset
|
53 #endif |
44184 | 54 #include <sys/stat.h> |
55 | |
48422
2346caa2a66a
Include unistd.h, string.h, stdlib.h,
Dave Love <fx@gnu.org>
parents:
46774
diff
changeset
|
56 /* Needed for SunOS4, for instance. */ |
2346caa2a66a
Include unistd.h, string.h, stdlib.h,
Dave Love <fx@gnu.org>
parents:
46774
diff
changeset
|
57 extern char *optarg; |
2346caa2a66a
Include unistd.h, string.h, stdlib.h,
Dave Love <fx@gnu.org>
parents:
46774
diff
changeset
|
58 extern int optind, opterr; |
2346caa2a66a
Include unistd.h, string.h, stdlib.h,
Dave Love <fx@gnu.org>
parents:
46774
diff
changeset
|
59 |
44184 | 60 #define MAX_ATTEMPTS 5 |
44481
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
61 #define MAX_SCORES 200 |
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
62 #define MAX_DATA_LEN 1024 |
44419
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
63 |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
64 /* Declare the prototype for a general external function. */ |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
65 #if defined (PROTOTYPES) || defined (WINDOWSNT) |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
66 #define P_(proto) proto |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
67 #else |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
68 #define P_(proto) () |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
69 #endif |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
70 |
44184 | 71 int |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
72 usage(err) |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
73 int err; |
44184 | 74 { |
75 fprintf(stdout, "Usage: update-game-score [-m MAX ] [ -r ] game/scorefile SCORE DATA\n"); | |
76 fprintf(stdout, " update-game-score -h\n"); | |
77 fprintf(stdout, " -h\t\tDisplay this help.\n"); | |
78 fprintf(stdout, " -m MAX\t\tLimit the maximum number of scores to MAX.\n"); | |
79 fprintf(stdout, " -r\t\tSort the scores in increasing order.\n"); | |
44987
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
80 fprintf(stdout, " -d DIR\t\tStore scores in DIR (only if not setuid).\n"); |
44184 | 81 exit(err); |
82 } | |
83 | |
84 int | |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
85 lock_file P_((const char *filename, void **state)); |
44184 | 86 int |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
87 unlock_file P_((const char *filename, void *state)); |
44184 | 88 |
89 struct score_entry | |
90 { | |
91 long score; | |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
92 char *username; |
44184 | 93 char *data; |
94 }; | |
95 | |
96 int | |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
97 read_scores P_((const char *filename, struct score_entry **scores, |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
98 int *count)); |
44184 | 99 int |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
100 push_score P_((struct score_entry **scores, int *count, |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
101 int newscore, char *username, char *newdata)); |
44184 | 102 void |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
103 sort_scores P_((struct score_entry *scores, int count, int reverse)); |
44184 | 104 int |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
105 write_scores P_((const char *filename, const struct score_entry *scores, |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
106 int count)); |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
107 |
48422
2346caa2a66a
Include unistd.h, string.h, stdlib.h,
Dave Love <fx@gnu.org>
parents:
46774
diff
changeset
|
108 void lose P_((const char *msg)) NO_RETURN; |
44184 | 109 |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
110 void lose(msg) |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
111 const char *msg; |
44481
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
112 { |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
113 fprintf(stderr, "%s\n", msg); |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
114 exit(1); |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
115 } |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
116 |
48422
2346caa2a66a
Include unistd.h, string.h, stdlib.h,
Dave Love <fx@gnu.org>
parents:
46774
diff
changeset
|
117 void lose_syserr P_((const char *msg)) NO_RETURN; |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
118 |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
119 void lose_syserr(msg) |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
120 const char *msg; |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
121 { |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
122 fprintf(stderr, "%s: %s\n", msg, strerror(errno)); |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
123 exit(1); |
44481
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
124 } |
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
125 |
44987
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
126 char * |
48422
2346caa2a66a
Include unistd.h, string.h, stdlib.h,
Dave Love <fx@gnu.org>
parents:
46774
diff
changeset
|
127 get_user_id P_ ((void)) |
44987
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
128 { |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
129 char *name; |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
130 struct passwd *buf = getpwuid(getuid()); |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
131 if (!buf) |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
132 { |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
133 int count = 1; |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
134 int uid = (int) getuid(); |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
135 int tuid = uid; |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
136 while (tuid /= 10) |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
137 count++; |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
138 name = malloc(count+1); |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
139 if (!name) |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
140 return NULL; |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
141 sprintf(name, "%d", uid); |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
142 return name; |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
143 } |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
144 return buf->pw_name; |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
145 } |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
146 |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
147 char * |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
148 get_prefix(running_suid, user_prefix) |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
149 int running_suid; |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
150 char *user_prefix; |
44987
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
151 { |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
152 if (!running_suid && user_prefix == NULL) |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
153 lose("Not using a shared game directory, and no prefix given."); |
44987
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
154 if (running_suid) |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
155 { |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
156 #ifdef HAVE_SHARED_GAME_DIR |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
157 return HAVE_SHARED_GAME_DIR; |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
158 #else |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
159 lose("This program was compiled without HAVE_SHARED_GAME_DIR,\n and should not be suid."); |
44987
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
160 #endif |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
161 } |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
162 return user_prefix; |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
163 } |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
164 |
44184 | 165 int |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
166 main(argc, argv) |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
167 int argc; |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
168 char **argv; |
44184 | 169 { |
44987
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
170 int c, running_suid; |
44184 | 171 void *lockstate; |
44987
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
172 char *user_id, *scorefile, *prefix, *user_prefix = NULL; |
44184 | 173 struct stat buf; |
174 struct score_entry *scores; | |
44481
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
175 int newscore, scorecount, reverse = 0, max = MAX_SCORES; |
44184 | 176 char *newdata; |
177 | |
178 srand(time(0)); | |
179 | |
44987
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
180 while ((c = getopt(argc, argv, "hrm:d:")) != -1) |
44184 | 181 switch (c) |
182 { | |
183 case 'h': | |
184 usage(0); | |
185 break; | |
44987
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
186 case 'd': |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
187 user_prefix = optarg; |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
188 break; |
44184 | 189 case 'r': |
190 reverse = 1; | |
191 break; | |
192 case 'm': | |
193 max = atoi(optarg); | |
44481
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
194 if (max > MAX_SCORES) |
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
195 max = MAX_SCORES; |
44184 | 196 break; |
197 default: | |
198 usage(1); | |
199 } | |
200 | |
201 if (optind+3 != argc) | |
202 usage(1); | |
44419
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
203 |
44987
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
204 running_suid = (getuid() != geteuid()); |
44419
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
205 |
44987
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
206 prefix = get_prefix(running_suid, user_prefix); |
44481
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
207 |
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
208 scorefile = malloc(strlen(prefix) + strlen(argv[optind]) + 2); |
44184 | 209 if (!scorefile) |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
210 lose_syserr("Couldn't allocate score file"); |
44481
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
211 |
44419
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
212 strcpy(scorefile, prefix); |
44481
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
213 strcat(scorefile, "/"); |
44184 | 214 strcat(scorefile, argv[optind]); |
215 newscore = atoi(argv[optind+1]); | |
216 newdata = argv[optind+2]; | |
44481
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
217 if (strlen(newdata) > MAX_DATA_LEN) |
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
218 newdata[MAX_DATA_LEN] = '\0'; |
44987
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
219 |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
220 if ((user_id = get_user_id()) == NULL) |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
221 lose_syserr("Couldn't determine user id"); |
44184 | 222 |
223 if (stat(scorefile, &buf) < 0) | |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
224 lose_syserr("Failed to access scores file"); |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
225 |
44184 | 226 if (lock_file(scorefile, &lockstate) < 0) |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
227 lose_syserr("Failed to lock scores file"); |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
228 |
44184 | 229 if (read_scores(scorefile, &scores, &scorecount) < 0) |
230 { | |
44481
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
231 unlock_file(scorefile, lockstate); |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
232 lose_syserr("Failed to read scores file"); |
44184 | 233 } |
44987
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
234 push_score(&scores, &scorecount, newscore, user_id, newdata); |
44481
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
235 /* Limit the number of scores. If we're using reverse sorting, then |
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
236 we should increment the beginning of the array, to skip over the |
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
237 *smallest* scores. Otherwise, we just decrement the number of |
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
238 scores, since the smallest will be at the end. */ |
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
239 if (scorecount > MAX_SCORES) |
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
240 scorecount -= (scorecount - MAX_SCORES); |
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
241 if (reverse) |
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
242 scores += (scorecount - MAX_SCORES); |
44184 | 243 sort_scores(scores, scorecount, reverse); |
244 if (write_scores(scorefile, scores, scorecount) < 0) | |
245 { | |
44481
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
246 unlock_file(scorefile, lockstate); |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
247 lose_syserr("Failed to write scores file"); |
44184 | 248 } |
249 unlock_file(scorefile, lockstate); | |
250 exit(0); | |
251 } | |
252 | |
253 int | |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
254 read_score(f, score) |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
255 FILE *f; |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
256 struct score_entry *score; |
44184 | 257 { |
258 int c; | |
259 if (feof(f)) | |
260 return 1; | |
261 while ((c = getc(f)) != EOF | |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
262 && isdigit(c)) |
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 score->score *= 10; |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
265 score->score += (c-48); |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
266 } |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
267 while ((c = getc(f)) != EOF |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
268 && isspace(c)) |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
269 ; |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
270 if (c == EOF) |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
271 return -1; |
44404
21e4d76a9e8a
Actually make previous changes work (oops).
Colin Walters <walters@gnu.org>
parents:
44402
diff
changeset
|
272 ungetc(c, f); |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
273 #ifdef HAVE_GETDELIM |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
274 { |
44566
7a0ad319b38f
(read_score): Fix type of second parameter
Andreas Schwab <schwab@suse.de>
parents:
44481
diff
changeset
|
275 size_t count = 0; |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
276 if (getdelim(&score->username, &count, ' ', f) < 1 |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
277 || score->username == NULL) |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
278 return -1; |
44789
d095e59dc01d
(read_score) [HAVE_GETDELIM]: Trim trailing space.
Colin Walters <walters@gnu.org>
parents:
44639
diff
changeset
|
279 /* Trim the space */ |
d095e59dc01d
(read_score) [HAVE_GETDELIM]: Trim trailing space.
Colin Walters <walters@gnu.org>
parents:
44639
diff
changeset
|
280 score->username[strlen(score->username)-1] = '\0'; |
44184 | 281 } |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
282 #else |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
283 { |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
284 int unameread = 0; |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
285 int unamelen = 30; |
44404
21e4d76a9e8a
Actually make previous changes work (oops).
Colin Walters <walters@gnu.org>
parents:
44402
diff
changeset
|
286 char *username = malloc(unamelen); |
21e4d76a9e8a
Actually make previous changes work (oops).
Colin Walters <walters@gnu.org>
parents:
44402
diff
changeset
|
287 if (!username) |
21e4d76a9e8a
Actually make previous changes work (oops).
Colin Walters <walters@gnu.org>
parents:
44402
diff
changeset
|
288 return -1; |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
289 |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
290 while ((c = getc(f)) != EOF |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
291 && !isspace(c)) |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
292 { |
44481
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
293 if (unameread >= unamelen-1) |
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
294 if (!(username = realloc(username, unamelen *= 2))) |
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
295 return -1; |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
296 username[unameread] = c; |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
297 unameread++; |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
298 } |
44404
21e4d76a9e8a
Actually make previous changes work (oops).
Colin Walters <walters@gnu.org>
parents:
44402
diff
changeset
|
299 if (c == EOF) |
21e4d76a9e8a
Actually make previous changes work (oops).
Colin Walters <walters@gnu.org>
parents:
44402
diff
changeset
|
300 return -1; |
21e4d76a9e8a
Actually make previous changes work (oops).
Colin Walters <walters@gnu.org>
parents:
44402
diff
changeset
|
301 username[unameread] = '\0'; |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
302 score->username = username; |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
303 } |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
304 #endif |
44184 | 305 #ifdef HAVE_GETLINE |
306 score->data = NULL; | |
44566
7a0ad319b38f
(read_score): Fix type of second parameter
Andreas Schwab <schwab@suse.de>
parents:
44481
diff
changeset
|
307 errno = 0; |
44184 | 308 { |
44566
7a0ad319b38f
(read_score): Fix type of second parameter
Andreas Schwab <schwab@suse.de>
parents:
44481
diff
changeset
|
309 size_t len; |
44184 | 310 if (getline(&score->data, &len, f) < 0) |
311 return -1; | |
44419
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
312 score->data[strlen(score->data)-1] = '\0'; |
44184 | 313 } |
314 #else | |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
315 { |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
316 int cur = 0; |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
317 int len = 16; |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
318 char *buf = malloc(len); |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
319 if (!buf) |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
320 return -1; |
44404
21e4d76a9e8a
Actually make previous changes work (oops).
Colin Walters <walters@gnu.org>
parents:
44402
diff
changeset
|
321 while ((c = getc(f)) != EOF |
21e4d76a9e8a
Actually make previous changes work (oops).
Colin Walters <walters@gnu.org>
parents:
44402
diff
changeset
|
322 && c != '\n') |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
323 { |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
324 if (cur >= len-1) |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
325 { |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
326 if (!(buf = realloc(buf, len *= 2))) |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
327 return -1; |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
328 } |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
329 buf[cur] = c; |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
330 cur++; |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
331 } |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
332 score->data = buf; |
44419
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
333 score->data[cur] = '\0'; |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
334 } |
44184 | 335 #endif |
336 return 0; | |
337 } | |
338 | |
339 int | |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
340 read_scores(filename, scores, count) |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
341 const char *filename; |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
342 struct score_entry **scores; |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
343 int *count; |
44184 | 344 { |
345 int readval, scorecount, cursize; | |
346 struct score_entry *ret; | |
347 FILE *f = fopen(filename, "r"); | |
348 if (!f) | |
349 return -1; | |
350 scorecount = 0; | |
351 cursize = 16; | |
352 ret = malloc(sizeof(struct score_entry) * cursize); | |
353 if (!ret) | |
354 return -1; | |
355 while ((readval = read_score(f, &ret[scorecount])) == 0) | |
356 { | |
357 /* We encoutered an error */ | |
358 if (readval < 0) | |
359 return -1; | |
360 scorecount++; | |
361 if (scorecount >= cursize) | |
362 { | |
363 ret = realloc(ret, cursize *= 2); | |
364 if (!ret) | |
365 return -1; | |
366 } | |
367 } | |
368 *count = scorecount; | |
369 *scores = ret; | |
370 return 0; | |
371 } | |
372 | |
373 int | |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
374 score_compare(a, b) |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
375 const void *a; |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
376 const void *b; |
44184 | 377 { |
378 const struct score_entry *sa = (const struct score_entry *) a; | |
379 const struct score_entry *sb = (const struct score_entry *) b; | |
380 return (sb->score > sa->score) - (sb->score < sa->score); | |
381 } | |
382 | |
383 int | |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
384 score_compare_reverse(a, b) |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
385 const void *a; |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
386 const void *b; |
44184 | 387 { |
388 const struct score_entry *sa = (const struct score_entry *) a; | |
389 const struct score_entry *sb = (const struct score_entry *) b; | |
390 return (sa->score > sb->score) - (sa->score < sb->score); | |
391 } | |
392 | |
393 int | |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
394 push_score(scores, count, newscore, username, newdata) |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
395 struct score_entry **scores; |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
396 int *count; int newscore; |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
397 char *username; |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
398 char *newdata; |
44184 | 399 { |
400 struct score_entry *newscores = realloc(*scores, | |
401 sizeof(struct score_entry) * ((*count) + 1)); | |
402 if (!newscores) | |
403 return -1; | |
404 newscores[*count].score = newscore; | |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
405 newscores[*count].username = username; |
44184 | 406 newscores[*count].data = newdata; |
407 (*count) += 1; | |
408 *scores = newscores; | |
409 return 0; | |
410 } | |
411 | |
412 void | |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
413 sort_scores(scores, count, reverse) |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
414 struct score_entry *scores; |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
415 int count; |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
416 int reverse; |
44184 | 417 { |
418 qsort(scores, count, sizeof(struct score_entry), | |
419 reverse ? score_compare_reverse : score_compare); | |
420 } | |
421 | |
422 int | |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
423 write_scores(filename, scores, count) |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
424 const char *filename; |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
425 const struct score_entry * scores; |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
426 int count; |
44184 | 427 { |
428 FILE *f; | |
429 int i; | |
430 char *tempfile = malloc(strlen(filename) + strlen(".tempXXXXXX") + 1); | |
431 if (!tempfile) | |
432 return -1; | |
433 strcpy(tempfile, filename); | |
434 strcat(tempfile, ".tempXXXXXX"); | |
44481
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
435 #ifdef HAVE_MKSTEMP |
44184 | 436 if (mkstemp(tempfile) < 0 |
44481
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
437 #else |
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
438 if (mktemp(tempfile) != tempfile |
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
439 #endif |
44184 | 440 || !(f = fopen(tempfile, "w"))) |
441 return -1; | |
442 for (i = 0; i < count; i++) | |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
443 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
|
444 scores[i].data) < 0) |
44184 | 445 return -1; |
446 fclose(f); | |
44481
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
447 if (rename(tempfile, filename) < 0) |
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
448 return -1; |
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
449 if (chmod(filename, 0644) < 0) |
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
450 return -1; |
44184 | 451 return 0; |
452 } | |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
453 |
44184 | 454 int |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
455 lock_file(filename, state) |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
456 const char *filename; |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
457 void **state; |
44184 | 458 { |
459 int fd; | |
44576
90866353c7bd
(lock_file): If the lock file is older than an hour, delete it. Reset
Colin Walters <walters@gnu.org>
parents:
44566
diff
changeset
|
460 struct stat buf; |
44184 | 461 int attempts = 0; |
462 char *lockext = ".lockfile"; | |
463 char *lockpath = malloc(strlen(filename) + strlen(lockext) + 60); | |
464 if (!lockpath) | |
465 return -1; | |
466 strcpy(lockpath, filename); | |
467 strcat(lockpath, lockext); | |
468 *state = lockpath; | |
469 trylock: | |
470 attempts++; | |
44576
90866353c7bd
(lock_file): If the lock file is older than an hour, delete it. Reset
Colin Walters <walters@gnu.org>
parents:
44566
diff
changeset
|
471 /* If the lock is over an hour old, delete it. */ |
90866353c7bd
(lock_file): If the lock file is older than an hour, delete it. Reset
Colin Walters <walters@gnu.org>
parents:
44566
diff
changeset
|
472 if (stat(lockpath, &buf) == 0 |
90866353c7bd
(lock_file): If the lock file is older than an hour, delete it. Reset
Colin Walters <walters@gnu.org>
parents:
44566
diff
changeset
|
473 && (difftime(buf.st_ctime, time(NULL) > 60*60))) |
90866353c7bd
(lock_file): If the lock file is older than an hour, delete it. Reset
Colin Walters <walters@gnu.org>
parents:
44566
diff
changeset
|
474 unlink(lockpath); |
44184 | 475 if ((fd = open(lockpath, O_CREAT | O_EXCL, 0600)) < 0) |
476 { | |
477 if (errno == EEXIST) | |
478 { | |
479 /* Break the lock; we won't corrupt the file, but we might | |
480 lose some scores. */ | |
481 if (attempts > MAX_ATTEMPTS) | |
44576
90866353c7bd
(lock_file): If the lock file is older than an hour, delete it. Reset
Colin Walters <walters@gnu.org>
parents:
44566
diff
changeset
|
482 { |
90866353c7bd
(lock_file): If the lock file is older than an hour, delete it. Reset
Colin Walters <walters@gnu.org>
parents:
44566
diff
changeset
|
483 unlink(lockpath); |
90866353c7bd
(lock_file): If the lock file is older than an hour, delete it. Reset
Colin Walters <walters@gnu.org>
parents:
44566
diff
changeset
|
484 attempts = 0; |
90866353c7bd
(lock_file): If the lock file is older than an hour, delete it. Reset
Colin Walters <walters@gnu.org>
parents:
44566
diff
changeset
|
485 } |
44481
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
486 sleep((rand() % 2)+1); |
44184 | 487 goto trylock; |
488 } | |
489 else | |
490 return -1; | |
491 } | |
492 close(fd); | |
493 return 0; | |
494 } | |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
495 |
44184 | 496 int |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
497 unlock_file(filename, state) |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
498 const char *filename; |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
499 void *state; |
44184 | 500 { |
501 char *lockpath = (char *) state; | |
502 int ret = unlink(lockpath); | |
503 int saved_errno = errno; | |
504 free(lockpath); | |
505 errno = saved_errno; | |
506 return ret; | |
507 } |