[monkey-bubble: 61/753] check for setfsgid() (used by new gnome-score) No more gnome-score-helper.
- From: Sven Herzberg <herzi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [monkey-bubble: 61/753] check for setfsgid() (used by new gnome-score) No more gnome-score-helper.
- Date: Wed, 14 Jul 2010 22:00:48 +0000 (UTC)
commit 38c687667594efd5faa7ae52104ff51b38718d55
Author: EST 1998 Nathan Bryant <bryant cs usm maine edu>
Date: Tue Feb 3 03:52:59 1998 +0000
check for setfsgid() (used by new gnome-score) No more gnome-score-helper.
Mon Feb 2 22:08:05 EST 1998 Nathan Bryant <bryant cs usm maine edu>
* configure.in: check for setfsgid() (used by new gnome-score)
* libgnome/gnome-score.c: No more gnome-score-helper. Games must now
be setgid games and call gnome_score_init("name of game here") before
anything else in main(). (Including gtk_init/gnome_init.)
* libgnome/gnome-score-helper.c: removed
* libgnome/Makefile.am: updated for no gnome-score-helper
* programs/gnomine/gnomine.c: added gnome_score_init
libgnome/gnome-score.c | 437 ++++++++++++++++++++++++++++++++++++++----------
1 files changed, 348 insertions(+), 89 deletions(-)
---
diff --git a/libgnome/gnome-score.c b/libgnome/gnome-score.c
index 9cf6127..b277496 100644
--- a/libgnome/gnome-score.c
+++ b/libgnome/gnome-score.c
@@ -1,109 +1,368 @@
+/*
+ * gnome-score.c
+ * originally by Elliot Lee, subsequently bashed around by Nathan Bryant
+ */
+
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#include <glib.h>
+#include <pwd.h>
+#include <ctype.h>
#include "gnome-defs.h"
#include "gnome-score.h"
+#include "gnome-util.h"
+
+#ifndef NSCORES
+#define NSCORES 10
+#endif
+
+#define SCORE_PATH GNOMELOCALSTATEDIR "/games"
+
+struct command
+{
+ gfloat score;
+ int level; /* length of level arg to gnome_score_log
+ * including null term */
+ gboolean ordering;
+};
+
+struct ascore_t
+{
+ gchar *username;
+ time_t scoretime;
+ gfloat score;
+};
+
+static int outfd = -1, infd = -1;
+static const gchar *defgamename;
+
+/********************** internal functions ***********************************/
+
+static gchar *
+gnome_get_score_file_name (const gchar * progname, const gchar * level)
+{
+ if (level)
+ return g_copy_strings (SCORE_PATH "/",
+ progname, ".", level, ".scores", NULL);
+ else
+ return g_copy_strings (SCORE_PATH "/",
+ progname, ".scores", NULL);
+}
+
+static void
+print_ascore (struct ascore_t *ascore, FILE * outfile)
+{
+ fprintf (outfile, "%f %ld %s\n", ascore->score,
+ (long int) ascore->scoretime, ascore->username);
+}
+
+static void
+free_ascore(struct ascore_t *data)
+{
+ g_free(data->username);
+ g_free(data);
+}
+
+static gint
+log_score (const gchar * progname, const gchar * level, gchar * username,
+ gfloat score, int ordering)
+{
+ FILE *infile;
+ FILE *outfile;
+ gchar buf[512], *buf2;
+ GList *scores = NULL, *anode;
+ gchar *name, *game_score_file;
+ gfloat ascore;
+ time_t atime;
+ struct ascore_t *anitem, *curscore;
+ int i;
+ gint retval = 1;
+ gint pos;
+
+ game_score_file = gnome_get_score_file_name (progname, level);
+
+ infile = fopen (game_score_file, "r");
+ if (infile)
+ {
+ while (fgets (buf, sizeof (buf), infile))
+ {
+ i = strlen (buf) - 1; /* Chomp */
+ while (isspace (buf[i]))
+ buf[i--] = '\0';
+
+ buf2 = strtok (buf, " ");
+ ascore = atof (buf2);
+ buf2 = strtok (NULL, " ");
+ (long int) atime = atoi (buf2);
+ buf2 = strtok (NULL, "\n");
+ name = strdup (buf2);
+
+ anitem = g_malloc (sizeof (struct ascore_t));
+ anitem->score = ascore;
+ anitem->username = name;
+ anitem->scoretime = atime;
+ scores = g_list_append (scores, (gpointer) anitem);
+ }
+ fclose (infile);
+ }
+ anitem = g_malloc (sizeof (struct ascore_t));
+ anitem->score = score;
+ anitem->username = g_strdup(username);
+ anitem->scoretime = time (NULL);
+
+ for (pos = 0, anode = scores;
+ pos < NSCORES && anode;
+ pos++, anode = anode->next)
+ {
+ curscore = anode->data;
+ if (ordering)
+ {
+ if (curscore->score < anitem->score)
+ break;
+ }
+ else
+ {
+ if (curscore->score > anitem->score)
+ break;
+ }
+ }
+
+ if (pos < NSCORES)
+ {
+ scores = g_list_insert (scores, anitem, pos);
+ if ((anode = g_list_nth (scores, NSCORES)))
+ {
+ free_ascore (anode->data);
+ scores =
+ g_list_remove_link (scores, g_list_nth (scores, NSCORES));
+ }
+ retval = pos + 1;
+ }
+ else
+ retval = 0;
+
+ /* we dont create the file; it must already exist */
+ truncate (game_score_file, 0);
+ outfile = fopen (game_score_file, "r+");
+
+ if (outfile)
+ {
+ g_list_foreach (scores, (GFunc) print_ascore, outfile);
+ fclose (outfile);
+ }
+ else
+ perror (game_score_file);
+
+ g_free (game_score_file);
+
+ g_list_foreach (scores, (GFunc) free_ascore, NULL);
+ g_list_free (scores);
+
+ return retval;
+}
+
+static int
+gnome_score_child (void)
+{
+ struct command cmd;
+ gchar *level;
+ struct passwd *pwd;
+ gint retval;
+#ifdef HAVE_SETFSGID
+ gid_t gid;
+
+ gid = getegid ();
+ setgid (getgid ());
+ setfsgid (gid);
+#endif
+ pwd = getpwuid (getuid ());
+ strtok(pwd->pw_gecos, ",");
+ while (read (STDIN_FILENO, &cmd, sizeof cmd) == sizeof cmd)
+ {
+ level = g_new (char, cmd.level);
+ if (read (STDIN_FILENO, level, cmd.level) != cmd.level)
+ return EXIT_FAILURE;
+ if (!*level) {
+ g_free(level);
+ level = NULL;
+ }
+ retval = log_score (defgamename, level, pwd->pw_gecos, cmd.score,
+ cmd.ordering);
+ if (write(STDOUT_FILENO, &retval, sizeof retval) != sizeof retval)
+ return EXIT_FAILURE;
+ if (level)
+ g_free(level);
+ }
+ return EXIT_SUCCESS;
+}
+
+static void
+drop_perms (void)
+{
+ gid_t gid = getegid ();
+
+ setregid (getgid (), getgid ()); /* on some os'es (eg linux) this
+ * incantation will also drop the
+ * saved gid */
+ /* see if we can set it back -- if we can, saved id wasnt dropped */
+ if (!setgid (gid))
+ {
+ g_warning ("losing saved gid implementation detected, "
+ "get a real OS :)\n");
+ setgid (getgid ());
+ }
+}
-#define GNOME_SCORE_C 1
-#include "gnome-score-helper.c"
-#undef GNOME_SCORE_C
+/*********************** external functions **********************************/
+
+/*
+ * gnome_score_init()
+ * creates a child process with which we communicate through a pair of pipes,
+ * then drops privileges.
+ * this should be called as the first statement in main().
+ * returns 0 on success, drops privs and returns -1 on failure
+ */
gint
-gnome_score_log(gfloat score,
- gchar *level,
- gboolean higher_to_lower_score_order)
+gnome_score_init (const gchar * gamename)
{
- int exitstatus;
- char buf[64];
- char buf2[64];
-
- pid_t childpid = fork();
-
- if(childpid == 0)
- {
- /* We are the child */
- g_snprintf(buf, sizeof(buf), "%f", score);
- g_snprintf(buf2, sizeof(buf2), "%d", higher_to_lower_score_order);
- execlp("gnome-score-helper", "gnome-score-helper",
- buf, level?level:"", buf2, NULL);
- _exit(99);
- }
-
- waitpid(childpid, &exitstatus, 0);
- if(WIFEXITED(exitstatus) && (WEXITSTATUS(exitstatus) != -1) )
- return (WEXITSTATUS(exitstatus));
- else
- {
- g_warning("Scorekeeping failed\n");
- return 0;
- }
+ int inpipe[2], outpipe[2];
+
+ if (!gamename)
+ gamename = "";
+ if (!(defgamename = g_strdup (gamename)) ||
+ pipe(inpipe))
+ {
+ drop_perms();
+ return -1;
+ }
+ if (pipe (outpipe))
+ {
+ close (inpipe[0]);
+ close (inpipe[1]);
+ drop_perms ();
+ return -1;
+ }
+ outfd = outpipe[1];
+ infd = inpipe[0];
+ switch (fork ())
+ {
+ case 0:
+ if (dup2 (outpipe[0], STDIN_FILENO) == -1 ||
+ dup2 (inpipe[1], STDOUT_FILENO) == -1)
+ exit (EXIT_FAILURE);
+ close(inpipe[0]);
+ close(inpipe[1]);
+ close(outpipe[0]);
+ close(outpipe[1]);
+ exit (gnome_score_child ());
+ case -1:
+ close (inpipe[0]);
+ close (inpipe[1]);
+ close (outpipe[0]);
+ close (outpipe[1]);
+ infd = outfd = -1;
+ drop_perms ();
+ return -1;
+ }
+ close(outpipe[0]);
+ close(inpipe[1]);
+ drop_perms ();
+ return 0;
}
gint
-gnome_score_get_notable(gchar *gamename,
- gchar *level,
- gchar ***names,
- gfloat **scores,
- time_t **scoretimes)
+gnome_score_log (gfloat score,
+ gchar * level,
+ gboolean higher_to_lower_score_order)
{
- GList *l_scores, *anode;
- struct ascore_t *curscore;
- gchar *realname;
- gchar *game_score_section;
- gint retval;
- gint i;
-
- g_return_val_if_fail(names != NULL, 0);
- g_return_val_if_fail(scores != NULL, 0);
-
- if (gamename == NULL)
- realname = gnome_get_program_name(getpid());
- else
- realname = g_strdup(gamename);
- if(!realname)
- return -1;
-
- game_score_section = g_copy_strings ("=" SCORE_PATH "/",
- realname, ".scores=", "/",
- level ? level : "Top Ten",
- "/", NULL);
-/* l_scores = read_scores (game_score_section); */
- g_free(realname);
- g_free(game_score_section);
-
- retval = g_list_length (l_scores);
-
- if(retval)
- {
- *names = g_malloc((retval+1) * sizeof(gchar*));
- *scores = g_malloc((retval+1) * sizeof(gfloat));
- *scoretimes = g_malloc((retval+1) * sizeof(time_t));
-
- for(i = 0, anode = l_scores;
- i < retval && anode;
- i++, anode = anode->next)
- {
- curscore = anode->data;
- (*names)[i] = curscore->username;
- (*scores)[i] = curscore->score;
- (*scoretimes)[i] = curscore->scoretime;
- }
- g_list_free (l_scores);
+ struct command cmd;
+ gint retval;
+
+ if (getgid () != getegid ())
+ {
+ g_error ("gnome_score_init must be called first thing in main()\n");
+ abort ();
+ }
+ if (infd == -1 || outfd == -1)
+ return 0;
+
+ cmd.score = score;
+ if (!level)
+ level = "";
+ cmd.level = strlen (level) + 1;
+ cmd.ordering = higher_to_lower_score_order;
+
+ if (write (outfd, &cmd, sizeof cmd) != sizeof cmd ||
+ write (outfd, level, cmd.level) != cmd.level ||
+ read (infd, &retval, sizeof retval) != sizeof retval)
+ {
+ close (outfd);
+ close (infd);
+ infd = outfd = -1;
+ return 0;
+ }
+ return retval;
+}
+gint
+gnome_score_get_notable (gchar * gamename,
+ gchar * level,
+ gchar *** names,
+ gfloat ** scores,
+ time_t ** scoretimes)
+{
+ const gchar *realname;
+ gchar buf[512], *buf2;
+ gchar *infile_name;
+ FILE *infile;
+ gint retval;
+
+ g_return_val_if_fail (names != NULL, 0);
+ g_return_val_if_fail (scores != NULL, 0);
+
+ if (gamename == NULL)
+ realname = defgamename;
+ else
+ realname = gamename;
+
+ infile_name = gnome_get_score_file_name (realname, level);
+
+ infile = fopen (infile_name, "r");
+ g_free (infile_name);
+
+ if (infile)
+ {
+ *names = g_malloc ((NSCORES + 1) * sizeof (gchar *));
+ *scores = g_malloc ((NSCORES + 1) * sizeof (gfloat));
+ *scoretimes = g_malloc ((NSCORES + 1) * sizeof (time_t));
+
+ for (retval = 0;
+ fgets (buf, sizeof (buf), infile) && retval < NSCORES;
+ retval++)
+ {
+ buf[strlen (buf) - 1] = 0;
+ buf2 = strtok (buf, " ");
+ (*scores)[retval] = atof (buf2);
+ buf2 = strtok (NULL, " ");
+ (*scoretimes)[retval] = atoi (buf2);
+ buf2 = strtok (NULL, "\n");
+ (*names)[retval] = g_strdup (buf2);
+ }
(*names)[retval] = NULL;
(*scores)[retval] = 0.0;
- (*scoretimes)[retval] = 0;
- }
- else
- {
- *names = NULL;
- *scores = NULL;
- *scoretimes = NULL;
- retval = 0;
- }
-
- return retval;
+ fclose (infile);
+ }
+ else
+ {
+ *names = NULL;
+ *scores = NULL;
+ retval = 0;
+ }
+ return retval;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]