summaryrefslogtreecommitdiff
path: root/lib-src
diff options
context:
space:
mode:
authorColin Walters <walters@gnu.org>2002-04-10 19:10:23 +0000
committerColin Walters <walters@gnu.org>2002-04-10 19:10:23 +0000
commit8eec804f6efd3023e00a8b3f3f22103c2aabe9a9 (patch)
tree570fb1d10763b35e6aec1cb0c14d4c8185605f59 /lib-src
parent1ba1fb11c0d8516249894ac08396152c3e1cd009 (diff)
(toplevel): Include stdarg.h.
(MAX_DATA_LEN, MAX_SCORES): New. (SCORE_FILE_PREFIX): If HAVE_SHARED_GAME_DIR is not defined, default to ~/.emacs.d/games. (get_user_id): Don't zero uid in the case where we can't get the username. (lose): New function. (main): Actually use `max', and default it to MAX_SCORES. Correctly handle new default for SCORE_FILE_PREFIX. Use `lose' function. (read_score): Handle the case of reading unamelen characters, then finishing. Use mktemp if mkstemp isn't available. (lock_file, unlock_file): Delete unused versions. (lock_file): Always sleep, even if we unlinked the lock file.
Diffstat (limited to 'lib-src')
-rw-r--r--lib-src/update-game-score.c179
1 files changed, 80 insertions, 99 deletions
diff --git a/lib-src/update-game-score.c b/lib-src/update-game-score.c
index 0e257e057f5..31d3737d95e 100644
--- a/lib-src/update-game-score.c
+++ b/lib-src/update-game-score.c
@@ -19,8 +19,12 @@ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* This program is allows a game to securely and atomically update a
- score file. It should be installed setgid, owned by an appropriate
- group like `games'.
+ score file. It should be installed setuid, owned by an appropriate
+ user like `games'.
+
+ Alternatively, it can be compiled without HAVE_SHARED_GAME_DIR
+ defined, and in that case it will store scores in the user's home
+ directory (it should NOT be setuid).
Created 2002/03/22, by Colin Walters <walters@debian.org>
*/
@@ -36,15 +40,22 @@ Boston, MA 02111-1307, USA. */
#include <pwd.h>
#include <ctype.h>
#include <fcntl.h>
+#include <stdarg.h>
#include <sys/stat.h>
#include <config.h>
#define MAX_ATTEMPTS 5
+#define MAX_SCORES 200
+#define MAX_DATA_LEN 1024
#ifdef HAVE_SHARED_GAME_DIR
#define SCORE_FILE_PREFIX HAVE_SHARED_GAME_DIR
#else
-#define SCORE_FILE_PREFIX "$HOME"
+#define SCORE_FILE_PREFIX "~/.emacs.d/games"
+#endif
+
+#if !defined (__GNUC__) || __GNUC__ < 2
+#define __attribute__(x)
#endif
int
@@ -90,7 +101,8 @@ get_user_id(struct passwd *buf)
{
int count = 1;
int uid = (int) getuid();
- while (uid /= 10)
+ int tuid = uid;
+ while (tuid /= 10)
count++;
name = malloc(count+1);
sprintf(name, "%d", uid);
@@ -107,6 +119,18 @@ get_home_dir(struct passwd *buf)
return buf->pw_dir;
}
+void lose(const char *msg, ...)
+ __attribute__ ((format (printf,1,0), noreturn));
+
+void lose(const char *msg, ...)
+{
+ va_list ap;
+ va_start(ap, msg);
+ vfprintf(stderr, msg, ap);
+ va_end(ap);
+ exit(1);
+}
+
int
main(int argc, char **argv)
{
@@ -115,7 +139,7 @@ main(int argc, char **argv)
char *scorefile, *prefix;
struct stat buf;
struct score_entry *scores;
- int newscore, scorecount, reverse = 0, max = -1;
+ int newscore, scorecount, reverse = 0, max = MAX_SCORES;
char *newdata;
struct passwd *passwdbuf;
@@ -132,6 +156,8 @@ main(int argc, char **argv)
break;
case 'm':
max = atoi(optarg);
+ if (max > MAX_SCORES)
+ max = MAX_SCORES;
break;
default:
usage(1);
@@ -142,62 +168,65 @@ main(int argc, char **argv)
passwdbuf = getpwuid(getuid());
- if (!strcmp(SCORE_FILE_PREFIX, "$HOME"))
+ if (!strncmp(SCORE_FILE_PREFIX, "~", 1))
{
- prefix = get_home_dir(passwdbuf);
- if (!prefix)
- {
- fprintf(stderr, "Unable to determine home directory\n");
- exit(1);
- }
+ char *homedir = get_home_dir(passwdbuf);
+ if (!homedir)
+ lose("Unable to determine home directory\n");
+ prefix = malloc(strlen(homedir) + strlen(SCORE_FILE_PREFIX) + 1);
+ strcpy(prefix, homedir);
+ /* Skip over the '~'. */
+ strcat(prefix, SCORE_FILE_PREFIX+1);
}
else
- prefix = SCORE_FILE_PREFIX;
-
- scorefile = malloc(strlen(prefix) + strlen(argv[optind]) + 1);
+ prefix = strdup(SCORE_FILE_PREFIX);
+
+ if (!prefix)
+ lose("Couldn't create score file name: %s\n", strerror(errno));
+
+ scorefile = malloc(strlen(prefix) + strlen(argv[optind]) + 2);
if (!scorefile)
- {
- fprintf(stderr, "Couldn't create score file name: %s\n",
- strerror(errno));
- goto fail;
- }
+ lose("Couldn't create score file name: %s\n", strerror(errno));
+
strcpy(scorefile, prefix);
+ free(prefix);
+ strcat(scorefile, "/");
strcat(scorefile, argv[optind]);
newscore = atoi(argv[optind+1]);
newdata = argv[optind+2];
+ if (strlen(newdata) > MAX_DATA_LEN)
+ newdata[MAX_DATA_LEN] = '\0';
if (stat(scorefile, &buf) < 0)
- {
- fprintf(stderr, "Failed to access scores file \"%s\": %s\n",
- scorefile, strerror(errno));
- goto fail;
- }
+ lose("Failed to access scores file \"%s\": %s\n", scorefile,
+ strerror(errno));
if (lock_file(scorefile, &lockstate) < 0)
- {
- fprintf(stderr, "Failed to lock scores file \"%s\": %s\n",
- scorefile, strerror(errno));
- goto fail;
- }
+ lose("Failed to lock scores file \"%s\": %s\n",
+ scorefile, strerror(errno));
if (read_scores(scorefile, &scores, &scorecount) < 0)
{
- fprintf(stderr, "Failed to read scores file \"%s\": %s\n",
- scorefile, strerror(errno));
- goto fail_unlock;
+ unlock_file(scorefile, lockstate);
+ lose("Failed to read scores file \"%s\": %s\n", scorefile,
+ strerror(errno));
}
push_score(&scores, &scorecount, newscore, get_user_id(passwdbuf), newdata);
+ /* Limit the number of scores. If we're using reverse sorting, then
+ we should increment the beginning of the array, to skip over the
+ *smallest* scores. Otherwise, we just decrement the number of
+ scores, since the smallest will be at the end. */
+ if (scorecount > MAX_SCORES)
+ scorecount -= (scorecount - MAX_SCORES);
+ if (reverse)
+ scores += (scorecount - MAX_SCORES);
sort_scores(scores, scorecount, reverse);
if (write_scores(scorefile, scores, scorecount) < 0)
{
- fprintf(stderr, "Failed to write scores file \"%s\": %s\n",
- scorefile, strerror(errno));
- goto fail_unlock;
+ unlock_file(scorefile, lockstate);
+ lose("Failed to write scores file \"%s\": %s\n", scorefile,
+ strerror(errno));
}
unlock_file(scorefile, lockstate);
exit(0);
- fail_unlock:
- unlock_file(scorefile, lockstate);
- fail:
- exit(1);
}
int
@@ -236,11 +265,9 @@ read_score(FILE *f, struct score_entry *score)
while ((c = getc(f)) != EOF
&& !isspace(c))
{
- if (unameread == unamelen)
- {
- if (!(username = realloc(username, unamelen *= 2)))
- return -1;
- }
+ if (unameread >= unamelen-1)
+ if (!(username = realloc(username, unamelen *= 2)))
+ return -1;
username[unameread] = c;
unameread++;
}
@@ -366,7 +393,11 @@ write_scores(const char *filename, const struct score_entry *scores,
return -1;
strcpy(tempfile, filename);
strcat(tempfile, ".tempXXXXXX");
+#ifdef HAVE_MKSTEMP
if (mkstemp(tempfile) < 0
+#else
+ if (mktemp(tempfile) != tempfile
+#endif
|| !(f = fopen(tempfile, "w")))
return -1;
for (i = 0; i < count; i++)
@@ -374,60 +405,13 @@ write_scores(const char *filename, const struct score_entry *scores,
scores[i].data) < 0)
return -1;
fclose(f);
- rename(tempfile, filename);
- return 0;
-}
-
-#if 0
-int
-lock_file(const char *filename, void **state)
-{
- struct flock lock;
- int *istate;
- int fd, attempts = 0, ret = 0;
- lock.l_type = F_WRLCK;
- lock.l_whence = SEEK_SET;
- lock.l_start = 0;
- lock.l_len = 0;
- istate = malloc(sizeof(int));
- if (!istate)
+ if (rename(tempfile, filename) < 0)
return -1;
- if ((fd = open(filename, O_RDWR, 0600)) < 0)
+ if (chmod(filename, 0644) < 0)
return -1;
- *istate = fd;
- trylock:
- attempts++;
- if ((ret = fcntl(fd, F_GETLK, &lock)) == -1)
- {
- if (ret == EACCES || ret == EAGAIN)
- if (attempts > MAX_ATTEMPTS)
- exit(1);
- else
- {
- sleep((rand() % 3)+1);
- goto trylock;
- }
- else
- ret = 0 ;
- }
- else
- ret = 0;
- *state = istate;
- return ret;
-}
-
-int
-unlock_file(const char *filename, void *state)
-{
- int fd, ret;
- fd = *((int *) state);
- free(state);
- ret = close(fd);
- return ret;
+ return 0;
}
-#else
-
int
lock_file(const char *filename, void **state)
{
@@ -450,8 +434,7 @@ lock_file(const char *filename, void **state)
lose some scores. */
if (attempts > MAX_ATTEMPTS)
unlink(lockpath);
- else
- sleep((rand() % 2)+1);
+ sleep((rand() % 2)+1);
goto trylock;
}
else
@@ -471,5 +454,3 @@ unlock_file(const char *filename, void *state)
errno = saved_errno;
return ret;
}
-
-#endif