Mercurial > emacs
annotate lib-src/update-game-score.c @ 87880:d9edfa21892c
*** empty log message ***
author | Thien-Thi Nguyen <ttn@gnuvola.org> |
---|---|
date | Mon, 21 Jan 2008 14:03:09 +0000 |
parents | 5714ff101fd9 |
children | 606f2d163a64 3a4bc081639c |
rev | line source |
---|---|
44184 | 1 /* update-game-score.c --- Update a score file |
79748 | 2 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 |
3 Free Software Foundation, Inc. | |
44184 | 4 |
5 This file is part of GNU Emacs. | |
6 | |
7 GNU Emacs is free software; you can redistribute it and/or modify | |
8 it under the terms of the GNU General Public License as published by | |
78257
1f2482de3237
Switch license to GPLv3 or later.
Glenn Morris <rgm@gnu.org>
parents:
75348
diff
changeset
|
9 the Free Software Foundation; either version 3, or (at your option) |
44184 | 10 any later version. |
11 | |
12 GNU Emacs is distributed in the hope that it will be useful, | |
13 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 GNU General Public License for more details. | |
16 | |
17 You should have received a copy of the GNU General Public License | |
18 along with GNU Emacs; see the file COPYING. If not, write to | |
64083 | 19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
20 Boston, MA 02110-1301, USA. */ | |
44184 | 21 |
22 /* 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
|
23 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
|
24 user like `games'. |
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
25 |
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
26 Alternatively, it can be compiled without HAVE_SHARED_GAME_DIR |
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
27 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
|
28 directory (it should NOT be setuid). |
44184 | 29 |
30 Created 2002/03/22, by Colin Walters <walters@debian.org> | |
31 */ | |
32 | |
44639
44995332ed1b
Move config.h before the other headers, to prevent compiler warnings
Eli Zaretskii <eliz@gnu.org>
parents:
44576
diff
changeset
|
33 #include <config.h> |
44995332ed1b
Move config.h before the other headers, to prevent compiler warnings
Eli Zaretskii <eliz@gnu.org>
parents:
44576
diff
changeset
|
34 |
48422
2346caa2a66a
Include unistd.h, string.h, stdlib.h,
Dave Love <fx@gnu.org>
parents:
46774
diff
changeset
|
35 #ifdef HAVE_UNISTD_H |
44184 | 36 #include <unistd.h> |
48422
2346caa2a66a
Include unistd.h, string.h, stdlib.h,
Dave Love <fx@gnu.org>
parents:
46774
diff
changeset
|
37 #endif |
44184 | 38 #include <errno.h> |
48422
2346caa2a66a
Include unistd.h, string.h, stdlib.h,
Dave Love <fx@gnu.org>
parents:
46774
diff
changeset
|
39 #ifdef HAVE_STRING_H |
44184 | 40 #include <string.h> |
48422
2346caa2a66a
Include unistd.h, string.h, stdlib.h,
Dave Love <fx@gnu.org>
parents:
46774
diff
changeset
|
41 #endif |
2346caa2a66a
Include unistd.h, string.h, stdlib.h,
Dave Love <fx@gnu.org>
parents:
46774
diff
changeset
|
42 #ifdef HAVE_STDLIB_H |
44184 | 43 #include <stdlib.h> |
48422
2346caa2a66a
Include unistd.h, string.h, stdlib.h,
Dave Love <fx@gnu.org>
parents:
46774
diff
changeset
|
44 #endif |
44184 | 45 #include <stdio.h> |
46 #include <time.h> | |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
47 #include <pwd.h> |
44184 | 48 #include <ctype.h> |
48422
2346caa2a66a
Include unistd.h, string.h, stdlib.h,
Dave Love <fx@gnu.org>
parents:
46774
diff
changeset
|
49 #ifdef HAVE_FCNTL_H |
44184 | 50 #include <fcntl.h> |
48422
2346caa2a66a
Include unistd.h, string.h, stdlib.h,
Dave Love <fx@gnu.org>
parents:
46774
diff
changeset
|
51 #endif |
2346caa2a66a
Include unistd.h, string.h, stdlib.h,
Dave Love <fx@gnu.org>
parents:
46774
diff
changeset
|
52 #ifdef STDC_HEADERS |
44481
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
53 #include <stdarg.h> |
48422
2346caa2a66a
Include unistd.h, string.h, stdlib.h,
Dave Love <fx@gnu.org>
parents:
46774
diff
changeset
|
54 #endif |
44184 | 55 #include <sys/stat.h> |
56 | |
48422
2346caa2a66a
Include unistd.h, string.h, stdlib.h,
Dave Love <fx@gnu.org>
parents:
46774
diff
changeset
|
57 /* Needed for SunOS4, for instance. */ |
2346caa2a66a
Include unistd.h, string.h, stdlib.h,
Dave Love <fx@gnu.org>
parents:
46774
diff
changeset
|
58 extern char *optarg; |
2346caa2a66a
Include unistd.h, string.h, stdlib.h,
Dave Love <fx@gnu.org>
parents:
46774
diff
changeset
|
59 extern int optind, opterr; |
2346caa2a66a
Include unistd.h, string.h, stdlib.h,
Dave Love <fx@gnu.org>
parents:
46774
diff
changeset
|
60 |
44184 | 61 #define MAX_ATTEMPTS 5 |
44481
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
62 #define MAX_SCORES 200 |
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
63 #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
|
64 |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
65 /* 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
|
66 #if defined (PROTOTYPES) || defined (WINDOWSNT) |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
67 #define P_(proto) proto |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
68 #else |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
69 #define P_(proto) () |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
70 #endif |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
71 |
51146
f20c52ac1b8d
(difftime) [!HAVE_DIFFTIME]: Define.
Dave Love <fx@gnu.org>
parents:
50718
diff
changeset
|
72 #ifndef HAVE_DIFFTIME |
f20c52ac1b8d
(difftime) [!HAVE_DIFFTIME]: Define.
Dave Love <fx@gnu.org>
parents:
50718
diff
changeset
|
73 /* OK on POSIX (time_t is arithmetic type) modulo overflow in subtraction. */ |
f20c52ac1b8d
(difftime) [!HAVE_DIFFTIME]: Define.
Dave Love <fx@gnu.org>
parents:
50718
diff
changeset
|
74 #define difftime(t1, t0) (double)((t1) - (t0)) |
f20c52ac1b8d
(difftime) [!HAVE_DIFFTIME]: Define.
Dave Love <fx@gnu.org>
parents:
50718
diff
changeset
|
75 #endif |
f20c52ac1b8d
(difftime) [!HAVE_DIFFTIME]: Define.
Dave Love <fx@gnu.org>
parents:
50718
diff
changeset
|
76 |
44184 | 77 int |
49594 | 78 usage (err) |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
79 int err; |
44184 | 80 { |
49594 | 81 fprintf (stdout, "Usage: update-game-score [-m MAX ] [ -r ] game/scorefile SCORE DATA\n"); |
82 fprintf (stdout, " update-game-score -h\n"); | |
83 fprintf (stdout, " -h\t\tDisplay this help.\n"); | |
84 fprintf (stdout, " -m MAX\t\tLimit the maximum number of scores to MAX.\n"); | |
85 fprintf (stdout, " -r\t\tSort the scores in increasing order.\n"); | |
86 fprintf (stdout, " -d DIR\t\tStore scores in DIR (only if not setuid).\n"); | |
87 exit (err); | |
44184 | 88 } |
89 | |
49594 | 90 int lock_file P_ ((const char *filename, void **state)); |
91 int unlock_file P_ ((const char *filename, void *state)); | |
44184 | 92 |
93 struct score_entry | |
94 { | |
95 long score; | |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
96 char *username; |
44184 | 97 char *data; |
98 }; | |
99 | |
49594 | 100 int read_scores P_ ((const char *filename, struct score_entry **scores, |
101 int *count)); | |
102 int push_score P_ ((struct score_entry **scores, int *count, | |
103 int newscore, char *username, char *newdata)); | |
104 void sort_scores P_ ((struct score_entry *scores, int count, int reverse)); | |
105 int write_scores P_ ((const char *filename, const struct score_entry *scores, | |
106 int count)); | |
107 | |
108 void lose P_ ((const char *msg)) NO_RETURN; | |
109 | |
44184 | 110 void |
49594 | 111 lose (msg) |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
112 const char *msg; |
44481
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
113 { |
49594 | 114 fprintf (stderr, "%s\n", msg); |
55442
a47704955f8d
Throughout, replace 0 destined for `exit' arg with `EXIT_SUCCESS'.
Thien-Thi Nguyen <ttn@gnuvola.org>
parents:
52401
diff
changeset
|
115 exit (EXIT_FAILURE); |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
116 } |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
117 |
49594 | 118 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
|
119 |
51146
f20c52ac1b8d
(difftime) [!HAVE_DIFFTIME]: Define.
Dave Love <fx@gnu.org>
parents:
50718
diff
changeset
|
120 /* Taken from sysdep.c. */ |
f20c52ac1b8d
(difftime) [!HAVE_DIFFTIME]: Define.
Dave Love <fx@gnu.org>
parents:
50718
diff
changeset
|
121 #ifndef HAVE_STRERROR |
f20c52ac1b8d
(difftime) [!HAVE_DIFFTIME]: Define.
Dave Love <fx@gnu.org>
parents:
50718
diff
changeset
|
122 #ifndef WINDOWSNT |
f20c52ac1b8d
(difftime) [!HAVE_DIFFTIME]: Define.
Dave Love <fx@gnu.org>
parents:
50718
diff
changeset
|
123 char * |
f20c52ac1b8d
(difftime) [!HAVE_DIFFTIME]: Define.
Dave Love <fx@gnu.org>
parents:
50718
diff
changeset
|
124 strerror (errnum) |
f20c52ac1b8d
(difftime) [!HAVE_DIFFTIME]: Define.
Dave Love <fx@gnu.org>
parents:
50718
diff
changeset
|
125 int errnum; |
f20c52ac1b8d
(difftime) [!HAVE_DIFFTIME]: Define.
Dave Love <fx@gnu.org>
parents:
50718
diff
changeset
|
126 { |
f20c52ac1b8d
(difftime) [!HAVE_DIFFTIME]: Define.
Dave Love <fx@gnu.org>
parents:
50718
diff
changeset
|
127 extern char *sys_errlist[]; |
f20c52ac1b8d
(difftime) [!HAVE_DIFFTIME]: Define.
Dave Love <fx@gnu.org>
parents:
50718
diff
changeset
|
128 extern int sys_nerr; |
f20c52ac1b8d
(difftime) [!HAVE_DIFFTIME]: Define.
Dave Love <fx@gnu.org>
parents:
50718
diff
changeset
|
129 |
f20c52ac1b8d
(difftime) [!HAVE_DIFFTIME]: Define.
Dave Love <fx@gnu.org>
parents:
50718
diff
changeset
|
130 if (errnum >= 0 && errnum < sys_nerr) |
f20c52ac1b8d
(difftime) [!HAVE_DIFFTIME]: Define.
Dave Love <fx@gnu.org>
parents:
50718
diff
changeset
|
131 return sys_errlist[errnum]; |
f20c52ac1b8d
(difftime) [!HAVE_DIFFTIME]: Define.
Dave Love <fx@gnu.org>
parents:
50718
diff
changeset
|
132 return (char *) "Unknown error"; |
f20c52ac1b8d
(difftime) [!HAVE_DIFFTIME]: Define.
Dave Love <fx@gnu.org>
parents:
50718
diff
changeset
|
133 } |
f20c52ac1b8d
(difftime) [!HAVE_DIFFTIME]: Define.
Dave Love <fx@gnu.org>
parents:
50718
diff
changeset
|
134 #endif /* not WINDOWSNT */ |
f20c52ac1b8d
(difftime) [!HAVE_DIFFTIME]: Define.
Dave Love <fx@gnu.org>
parents:
50718
diff
changeset
|
135 #endif /* ! HAVE_STRERROR */ |
f20c52ac1b8d
(difftime) [!HAVE_DIFFTIME]: Define.
Dave Love <fx@gnu.org>
parents:
50718
diff
changeset
|
136 |
49594 | 137 void |
138 lose_syserr (msg) | |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
139 const char *msg; |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
140 { |
49594 | 141 fprintf (stderr, "%s: %s\n", msg, strerror (errno)); |
55442
a47704955f8d
Throughout, replace 0 destined for `exit' arg with `EXIT_SUCCESS'.
Thien-Thi Nguyen <ttn@gnuvola.org>
parents:
52401
diff
changeset
|
142 exit (EXIT_FAILURE); |
44481
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
143 } |
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
144 |
44987
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
145 char * |
48422
2346caa2a66a
Include unistd.h, string.h, stdlib.h,
Dave Love <fx@gnu.org>
parents:
46774
diff
changeset
|
146 get_user_id P_ ((void)) |
44987
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
147 { |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
148 char *name; |
49594 | 149 struct passwd *buf = getpwuid (getuid ()); |
44987
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
150 if (!buf) |
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 int count = 1; |
49594 | 153 int uid = (int) getuid (); |
44987
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
154 int tuid = uid; |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
155 while (tuid /= 10) |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
156 count++; |
49594 | 157 name = malloc (count+1); |
44987
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
158 if (!name) |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
159 return NULL; |
49594 | 160 sprintf (name, "%d", uid); |
44987
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
161 return name; |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
162 } |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
163 return buf->pw_name; |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
164 } |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
165 |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
166 char * |
49594 | 167 get_prefix (running_suid, user_prefix) |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
168 int running_suid; |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
169 char *user_prefix; |
44987
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
170 { |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
171 if (!running_suid && user_prefix == NULL) |
49594 | 172 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
|
173 if (running_suid) |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
174 { |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
175 #ifdef HAVE_SHARED_GAME_DIR |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
176 return HAVE_SHARED_GAME_DIR; |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
177 #else |
49594 | 178 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
|
179 #endif |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
180 } |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
181 return user_prefix; |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
182 } |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
183 |
44184 | 184 int |
49594 | 185 main (argc, argv) |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
186 int argc; |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
187 char **argv; |
44184 | 188 { |
44987
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
189 int c, running_suid; |
44184 | 190 void *lockstate; |
44987
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
191 char *user_id, *scorefile, *prefix, *user_prefix = NULL; |
44184 | 192 struct stat buf; |
193 struct score_entry *scores; | |
44481
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
194 int newscore, scorecount, reverse = 0, max = MAX_SCORES; |
44184 | 195 char *newdata; |
196 | |
49594 | 197 srand (time (0)); |
44184 | 198 |
49594 | 199 while ((c = getopt (argc, argv, "hrm:d:")) != -1) |
44184 | 200 switch (c) |
201 { | |
202 case 'h': | |
55442
a47704955f8d
Throughout, replace 0 destined for `exit' arg with `EXIT_SUCCESS'.
Thien-Thi Nguyen <ttn@gnuvola.org>
parents:
52401
diff
changeset
|
203 usage (EXIT_SUCCESS); |
44184 | 204 break; |
44987
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
205 case 'd': |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
206 user_prefix = optarg; |
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
207 break; |
44184 | 208 case 'r': |
209 reverse = 1; | |
210 break; | |
211 case 'm': | |
49594 | 212 max = atoi (optarg); |
44481
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
213 if (max > MAX_SCORES) |
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
214 max = MAX_SCORES; |
44184 | 215 break; |
216 default: | |
55442
a47704955f8d
Throughout, replace 0 destined for `exit' arg with `EXIT_SUCCESS'.
Thien-Thi Nguyen <ttn@gnuvola.org>
parents:
52401
diff
changeset
|
217 usage (EXIT_FAILURE); |
44184 | 218 } |
219 | |
220 if (optind+3 != argc) | |
55442
a47704955f8d
Throughout, replace 0 destined for `exit' arg with `EXIT_SUCCESS'.
Thien-Thi Nguyen <ttn@gnuvola.org>
parents:
52401
diff
changeset
|
221 usage (EXIT_FAILURE); |
44419
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
222 |
49594 | 223 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
|
224 |
49594 | 225 prefix = get_prefix (running_suid, user_prefix); |
44481
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
226 |
49594 | 227 scorefile = malloc (strlen (prefix) + strlen (argv[optind]) + 2); |
44184 | 228 if (!scorefile) |
49594 | 229 lose_syserr ("Couldn't allocate score file"); |
44481
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
230 |
49594 | 231 strcpy (scorefile, prefix); |
232 strcat (scorefile, "/"); | |
233 strcat (scorefile, argv[optind]); | |
234 newscore = atoi (argv[optind+1]); | |
44184 | 235 newdata = argv[optind+2]; |
49594 | 236 if (strlen (newdata) > MAX_DATA_LEN) |
44481
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
237 newdata[MAX_DATA_LEN] = '\0'; |
44987
cc0ab9acdc46
(SCORE_FILE_PREFIX): Delete.
Colin Walters <walters@gnu.org>
parents:
44789
diff
changeset
|
238 |
49595
ca4fb31aae14
(push_score, read_scores): Cast values of malloc and realloc.
Richard M. Stallman <rms@gnu.org>
parents:
49594
diff
changeset
|
239 user_id = get_user_id (); |
ca4fb31aae14
(push_score, read_scores): Cast values of malloc and realloc.
Richard M. Stallman <rms@gnu.org>
parents:
49594
diff
changeset
|
240 if (user_id == NULL) |
49594 | 241 lose_syserr ("Couldn't determine user id"); |
49600
23a1cea22d13
Trailing whitespace deleted.
Juanma Barranquero <lekktu@gmail.com>
parents:
49595
diff
changeset
|
242 |
49594 | 243 if (stat (scorefile, &buf) < 0) |
244 lose_syserr ("Failed to access scores file"); | |
49600
23a1cea22d13
Trailing whitespace deleted.
Juanma Barranquero <lekktu@gmail.com>
parents:
49595
diff
changeset
|
245 |
49594 | 246 if (lock_file (scorefile, &lockstate) < 0) |
247 lose_syserr ("Failed to lock scores file"); | |
49600
23a1cea22d13
Trailing whitespace deleted.
Juanma Barranquero <lekktu@gmail.com>
parents:
49595
diff
changeset
|
248 |
49594 | 249 if (read_scores (scorefile, &scores, &scorecount) < 0) |
44184 | 250 { |
49594 | 251 unlock_file (scorefile, lockstate); |
252 lose_syserr ("Failed to read scores file"); | |
44184 | 253 } |
49594 | 254 push_score (&scores, &scorecount, newscore, user_id, newdata); |
44481
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
255 /* 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
|
256 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
|
257 *smallest* scores. Otherwise, we just decrement the number of |
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
258 scores, since the smallest will be at the end. */ |
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
259 if (scorecount > MAX_SCORES) |
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
260 scorecount -= (scorecount - MAX_SCORES); |
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
261 if (reverse) |
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
262 scores += (scorecount - MAX_SCORES); |
49594 | 263 sort_scores (scores, scorecount, reverse); |
264 if (write_scores (scorefile, scores, scorecount) < 0) | |
44184 | 265 { |
49594 | 266 unlock_file (scorefile, lockstate); |
267 lose_syserr ("Failed to write scores file"); | |
44184 | 268 } |
49594 | 269 unlock_file (scorefile, lockstate); |
55442
a47704955f8d
Throughout, replace 0 destined for `exit' arg with `EXIT_SUCCESS'.
Thien-Thi Nguyen <ttn@gnuvola.org>
parents:
52401
diff
changeset
|
270 exit (EXIT_SUCCESS); |
44184 | 271 } |
272 | |
273 int | |
49594 | 274 read_score (f, score) |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
275 FILE *f; |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
276 struct score_entry *score; |
44184 | 277 { |
278 int c; | |
49594 | 279 if (feof (f)) |
44184 | 280 return 1; |
49594 | 281 while ((c = getc (f)) != EOF |
282 && isdigit (c)) | |
44402
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 score->score *= 10; |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
285 score->score += (c-48); |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
286 } |
49594 | 287 while ((c = getc (f)) != EOF |
288 && isspace (c)) | |
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 if (c == EOF) |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
291 return -1; |
49594 | 292 ungetc (c, f); |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
293 #ifdef HAVE_GETDELIM |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
294 { |
44566
7a0ad319b38f
(read_score): Fix type of second parameter
Andreas Schwab <schwab@suse.de>
parents:
44481
diff
changeset
|
295 size_t count = 0; |
49594 | 296 if (getdelim (&score->username, &count, ' ', f) < 1 |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
297 || score->username == NULL) |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
298 return -1; |
44789
d095e59dc01d
(read_score) [HAVE_GETDELIM]: Trim trailing space.
Colin Walters <walters@gnu.org>
parents:
44639
diff
changeset
|
299 /* Trim the space */ |
49594 | 300 score->username[strlen (score->username)-1] = '\0'; |
44184 | 301 } |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
302 #else |
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 int unameread = 0; |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
305 int unamelen = 30; |
49594 | 306 char *username = malloc (unamelen); |
44404
21e4d76a9e8a
Actually make previous changes work (oops).
Colin Walters <walters@gnu.org>
parents:
44402
diff
changeset
|
307 if (!username) |
21e4d76a9e8a
Actually make previous changes work (oops).
Colin Walters <walters@gnu.org>
parents:
44402
diff
changeset
|
308 return -1; |
49600
23a1cea22d13
Trailing whitespace deleted.
Juanma Barranquero <lekktu@gmail.com>
parents:
49595
diff
changeset
|
309 |
49594 | 310 while ((c = getc (f)) != EOF |
311 && !isspace (c)) | |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
312 { |
44481
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
313 if (unameread >= unamelen-1) |
49594 | 314 if (!(username = realloc (username, unamelen *= 2))) |
44481
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
315 return -1; |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
316 username[unameread] = c; |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
317 unameread++; |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
318 } |
49600
23a1cea22d13
Trailing whitespace deleted.
Juanma Barranquero <lekktu@gmail.com>
parents:
49595
diff
changeset
|
319 if (c == EOF) |
44404
21e4d76a9e8a
Actually make previous changes work (oops).
Colin Walters <walters@gnu.org>
parents:
44402
diff
changeset
|
320 return -1; |
21e4d76a9e8a
Actually make previous changes work (oops).
Colin Walters <walters@gnu.org>
parents:
44402
diff
changeset
|
321 username[unameread] = '\0'; |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
322 score->username = username; |
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 #endif |
44184 | 325 #ifdef HAVE_GETLINE |
326 score->data = NULL; | |
44566
7a0ad319b38f
(read_score): Fix type of second parameter
Andreas Schwab <schwab@suse.de>
parents:
44481
diff
changeset
|
327 errno = 0; |
44184 | 328 { |
44566
7a0ad319b38f
(read_score): Fix type of second parameter
Andreas Schwab <schwab@suse.de>
parents:
44481
diff
changeset
|
329 size_t len; |
49594 | 330 if (getline (&score->data, &len, f) < 0) |
44184 | 331 return -1; |
49594 | 332 score->data[strlen (score->data)-1] = '\0'; |
44184 | 333 } |
334 #else | |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
335 { |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
336 int cur = 0; |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
337 int len = 16; |
49594 | 338 char *buf = malloc (len); |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
339 if (!buf) |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
340 return -1; |
49594 | 341 while ((c = getc (f)) != EOF |
44404
21e4d76a9e8a
Actually make previous changes work (oops).
Colin Walters <walters@gnu.org>
parents:
44402
diff
changeset
|
342 && c != '\n') |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
343 { |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
344 if (cur >= len-1) |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
345 { |
49594 | 346 if (!(buf = realloc (buf, len *= 2))) |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
347 return -1; |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
348 } |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
349 buf[cur] = c; |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
350 cur++; |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
351 } |
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
352 score->data = buf; |
44419
16b3622178f9
update-game-score.c (SCORE_FILE_PREFIX): Don't hardcode.
Colin Walters <walters@gnu.org>
parents:
44404
diff
changeset
|
353 score->data[cur] = '\0'; |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
354 } |
44184 | 355 #endif |
356 return 0; | |
357 } | |
358 | |
359 int | |
49594 | 360 read_scores (filename, scores, count) |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
361 const char *filename; |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
362 struct score_entry **scores; |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
363 int *count; |
44184 | 364 { |
365 int readval, scorecount, cursize; | |
366 struct score_entry *ret; | |
49594 | 367 FILE *f = fopen (filename, "r"); |
49600
23a1cea22d13
Trailing whitespace deleted.
Juanma Barranquero <lekktu@gmail.com>
parents:
49595
diff
changeset
|
368 if (!f) |
44184 | 369 return -1; |
370 scorecount = 0; | |
371 cursize = 16; | |
49595
ca4fb31aae14
(push_score, read_scores): Cast values of malloc and realloc.
Richard M. Stallman <rms@gnu.org>
parents:
49594
diff
changeset
|
372 ret = (struct score_entry *) malloc (sizeof (struct score_entry) * cursize); |
49600
23a1cea22d13
Trailing whitespace deleted.
Juanma Barranquero <lekktu@gmail.com>
parents:
49595
diff
changeset
|
373 if (!ret) |
44184 | 374 return -1; |
49594 | 375 while ((readval = read_score (f, &ret[scorecount])) == 0) |
44184 | 376 { |
377 /* We encoutered an error */ | |
378 if (readval < 0) | |
379 return -1; | |
380 scorecount++; | |
381 if (scorecount >= cursize) | |
382 { | |
50718
240f333f936c
(read_scores): Fix corruption of score files.
Juanma Barranquero <lekktu@gmail.com>
parents:
49600
diff
changeset
|
383 cursize *= 2; |
240f333f936c
(read_scores): Fix corruption of score files.
Juanma Barranquero <lekktu@gmail.com>
parents:
49600
diff
changeset
|
384 ret = (struct score_entry *) |
240f333f936c
(read_scores): Fix corruption of score files.
Juanma Barranquero <lekktu@gmail.com>
parents:
49600
diff
changeset
|
385 realloc (ret, (sizeof (struct score_entry) * cursize)); |
44184 | 386 if (!ret) |
387 return -1; | |
388 } | |
389 } | |
390 *count = scorecount; | |
391 *scores = ret; | |
392 return 0; | |
393 } | |
394 | |
395 int | |
49594 | 396 score_compare (a, b) |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
397 const void *a; |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
398 const void *b; |
44184 | 399 { |
400 const struct score_entry *sa = (const struct score_entry *) a; | |
401 const struct score_entry *sb = (const struct score_entry *) b; | |
402 return (sb->score > sa->score) - (sb->score < sa->score); | |
403 } | |
404 | |
405 int | |
49594 | 406 score_compare_reverse (a, b) |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
407 const void *a; |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
408 const void *b; |
44184 | 409 { |
410 const struct score_entry *sa = (const struct score_entry *) a; | |
411 const struct score_entry *sb = (const struct score_entry *) b; | |
412 return (sa->score > sb->score) - (sa->score < sb->score); | |
413 } | |
414 | |
415 int | |
49600
23a1cea22d13
Trailing whitespace deleted.
Juanma Barranquero <lekktu@gmail.com>
parents:
49595
diff
changeset
|
416 push_score (scores, count, newscore, username, newdata) |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
417 struct score_entry **scores; |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
418 int *count; int newscore; |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
419 char *username; |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
420 char *newdata; |
44184 | 421 { |
49594 | 422 struct score_entry *newscores |
49595
ca4fb31aae14
(push_score, read_scores): Cast values of malloc and realloc.
Richard M. Stallman <rms@gnu.org>
parents:
49594
diff
changeset
|
423 = (struct score_entry *) realloc (*scores, |
ca4fb31aae14
(push_score, read_scores): Cast values of malloc and realloc.
Richard M. Stallman <rms@gnu.org>
parents:
49594
diff
changeset
|
424 sizeof (struct score_entry) * ((*count) + 1)); |
44184 | 425 if (!newscores) |
426 return -1; | |
427 newscores[*count].score = newscore; | |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
428 newscores[*count].username = username; |
44184 | 429 newscores[*count].data = newdata; |
430 (*count) += 1; | |
431 *scores = newscores; | |
432 return 0; | |
433 } | |
49600
23a1cea22d13
Trailing whitespace deleted.
Juanma Barranquero <lekktu@gmail.com>
parents:
49595
diff
changeset
|
434 |
44184 | 435 void |
49594 | 436 sort_scores (scores, count, reverse) |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
437 struct score_entry *scores; |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
438 int count; |
49600
23a1cea22d13
Trailing whitespace deleted.
Juanma Barranquero <lekktu@gmail.com>
parents:
49595
diff
changeset
|
439 int reverse; |
44184 | 440 { |
49594 | 441 qsort (scores, count, sizeof (struct score_entry), |
44184 | 442 reverse ? score_compare_reverse : score_compare); |
443 } | |
444 | |
445 int | |
49594 | 446 write_scores (filename, scores, count) |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
447 const char *filename; |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
448 const struct score_entry * scores; |
49600
23a1cea22d13
Trailing whitespace deleted.
Juanma Barranquero <lekktu@gmail.com>
parents:
49595
diff
changeset
|
449 int count; |
44184 | 450 { |
49600
23a1cea22d13
Trailing whitespace deleted.
Juanma Barranquero <lekktu@gmail.com>
parents:
49595
diff
changeset
|
451 FILE *f; |
44184 | 452 int i; |
49594 | 453 char *tempfile = malloc (strlen (filename) + strlen (".tempXXXXXX") + 1); |
44184 | 454 if (!tempfile) |
455 return -1; | |
49594 | 456 strcpy (tempfile, filename); |
457 strcat (tempfile, ".tempXXXXXX"); | |
44481
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
458 #ifdef HAVE_MKSTEMP |
49594 | 459 if (mkstemp (tempfile) < 0 |
44481
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
460 #else |
49594 | 461 if (mktemp (tempfile) != tempfile |
44481
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
462 #endif |
49594 | 463 || !(f = fopen (tempfile, "w"))) |
44184 | 464 return -1; |
465 for (i = 0; i < count; i++) | |
49594 | 466 if (fprintf (f, "%ld %s %s\n", scores[i].score, scores[i].username, |
44402
968fd5ccea65
(toplevel): Include pwd.h.
Colin Walters <walters@gnu.org>
parents:
44184
diff
changeset
|
467 scores[i].data) < 0) |
44184 | 468 return -1; |
49594 | 469 fclose (f); |
470 if (rename (tempfile, filename) < 0) | |
44481
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
471 return -1; |
49594 | 472 if (chmod (filename, 0644) < 0) |
44481
a0dc261f564a
(toplevel): Include stdarg.h.
Colin Walters <walters@gnu.org>
parents:
44419
diff
changeset
|
473 return -1; |
44184 | 474 return 0; |
475 } | |
49600
23a1cea22d13
Trailing whitespace deleted.
Juanma Barranquero <lekktu@gmail.com>
parents:
49595
diff
changeset
|
476 |
44184 | 477 int |
49594 | 478 lock_file (filename, state) |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
479 const char *filename; |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
480 void **state; |
44184 | 481 { |
482 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
|
483 struct stat buf; |
44184 | 484 int attempts = 0; |
485 char *lockext = ".lockfile"; | |
49594 | 486 char *lockpath = malloc (strlen (filename) + strlen (lockext) + 60); |
44184 | 487 if (!lockpath) |
488 return -1; | |
49594 | 489 strcpy (lockpath, filename); |
490 strcat (lockpath, lockext); | |
44184 | 491 *state = lockpath; |
492 trylock: | |
493 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
|
494 /* If the lock is over an hour old, delete it. */ |
49594 | 495 if (stat (lockpath, &buf) == 0 |
496 && (difftime (buf.st_ctime, time (NULL) > 60*60))) | |
497 unlink (lockpath); | |
49595
ca4fb31aae14
(push_score, read_scores): Cast values of malloc and realloc.
Richard M. Stallman <rms@gnu.org>
parents:
49594
diff
changeset
|
498 fd = open (lockpath, O_CREAT | O_EXCL, 0600); |
ca4fb31aae14
(push_score, read_scores): Cast values of malloc and realloc.
Richard M. Stallman <rms@gnu.org>
parents:
49594
diff
changeset
|
499 if (fd < 0) |
44184 | 500 { |
501 if (errno == EEXIST) | |
502 { | |
503 /* Break the lock; we won't corrupt the file, but we might | |
504 lose some scores. */ | |
505 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
|
506 { |
49594 | 507 unlink (lockpath); |
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
|
508 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
|
509 } |
49594 | 510 sleep ((rand () % 2)+1); |
44184 | 511 goto trylock; |
512 } | |
513 else | |
514 return -1; | |
515 } | |
49594 | 516 close (fd); |
44184 | 517 return 0; |
518 } | |
49600
23a1cea22d13
Trailing whitespace deleted.
Juanma Barranquero <lekktu@gmail.com>
parents:
49595
diff
changeset
|
519 |
44184 | 520 int |
49594 | 521 unlock_file (filename, state) |
46774
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
522 const char *filename; |
7411dc9e5008
(P_): New macro. Use it for all prototypes.
Colin Walters <walters@gnu.org>
parents:
44987
diff
changeset
|
523 void *state; |
44184 | 524 { |
525 char *lockpath = (char *) state; | |
49594 | 526 int ret = unlink (lockpath); |
44184 | 527 int saved_errno = errno; |
49594 | 528 free (lockpath); |
44184 | 529 errno = saved_errno; |
530 return ret; | |
531 } | |
52401 | 532 |
533 /* arch-tag: 2bf5c52e-4beb-463a-954e-c58b9c64736b | |
534 (do not change this comment) */ | |
55442
a47704955f8d
Throughout, replace 0 destined for `exit' arg with `EXIT_SUCCESS'.
Thien-Thi Nguyen <ttn@gnuvola.org>
parents:
52401
diff
changeset
|
535 |
a47704955f8d
Throughout, replace 0 destined for `exit' arg with `EXIT_SUCCESS'.
Thien-Thi Nguyen <ttn@gnuvola.org>
parents:
52401
diff
changeset
|
536 /* update-game-score.c ends here */ |