[gnome-nibbles/gnome-3-10] Copy scores-backend.c and setgid-io.c from glines
- From: Michael Catanzaro <mcatanzaro src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-nibbles/gnome-3-10] Copy scores-backend.c and setgid-io.c from glines
- Date: Wed, 6 Nov 2013 04:40:08 +0000 (UTC)
commit 126f83d67414cc4e3b3e4c013fdb94b37de8cc84
Author: Michael Catanzaro <mcatanzaro gnome org>
Date: Tue Nov 5 22:30:16 2013 -0600
Copy scores-backend.c and setgid-io.c from glines
For some reason we were stuck with a stub instead of a real copy of
games-scores-backend.
src/Makefile.am | 2 +
src/games-scores-backend.c | 223 +++++++++++++++++-
src/games-scores-backend.h | 4 +
src/games-setgid-io.c | 558 ++++++++++++++++++++++++++++++++++++++++++++
src/games-setgid-io.h | 38 +++
5 files changed, 823 insertions(+), 2 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 825d1ad..6bfbcda 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -25,6 +25,8 @@ gnome_nibbles_SOURCES = \
games-scores-dialog.h \
games-scores-backend.c \
games-scores-backend.h \
+ games-setgid-io.c \
+ games-setgid-io.h \
gnibbles.h \
gnibbles.c \
properties.h \
diff --git a/src/games-scores-backend.c b/src/games-scores-backend.c
index 6d138a9..f574713 100644
--- a/src/games-scores-backend.c
+++ b/src/games-scores-backend.c
@@ -30,7 +30,14 @@
#include "games-scores.h"
#include "games-scores-backend.h"
+#ifdef ENABLE_SETGID
+#include "games-setgid-io.h"
+#endif
+
struct GamesScoresBackendPrivate {
+#ifdef ENABLE_SETGID
+ gboolean setgid_io_initialized;
+#endif
GList *scores_list;
GamesScoreStyle style;
time_t timestamp;
@@ -43,7 +50,9 @@ G_DEFINE_TYPE (GamesScoresBackend, games_scores_backend, G_TYPE_OBJECT);
void
games_scores_backend_startup (void)
{
-
+#ifdef ENABLE_SETGID
+ setgid_io_init ();
+#endif
}
static void
@@ -102,7 +111,56 @@ games_scores_backend_new (GamesScoreStyle style,
return backend;
}
+#ifdef ENABLE_SETGID
+
+/* Get a lock on the scores file. Block until it is available.
+ * This also supplies the file descriptor we need. The return value
+ * is whether we were succesful or not. */
+static gboolean
+games_scores_backend_get_lock (GamesScoresBackend * self)
+{
+ gint error;
+
+ if (self->priv->fd != -1) {
+ /* Assume we already have the lock and rewind the file to
+ * the beginning. */
+ setgid_io_seek (self->priv->fd, 0, SEEK_SET);
+ return TRUE; /* Assume we already have the lock. */
+ }
+
+ self->priv->fd = setgid_io_open (self->priv->filename, O_RDWR);
+ if (self->priv->fd == -1) {
+ return FALSE;
+ }
+
+ error = setgid_io_lock (self->priv->fd);
+
+ if (error == -1) {
+ setgid_io_close (self->priv->fd);
+ self->priv->fd = -1;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/* Release the lock on the scores file and dispose of the fd. */
+/* We ignore errors, there is nothing we can do about them. */
+static void
+games_scores_backend_release_lock (GamesScoresBackend * self)
+{
+ /* We don't have a lock, ignore this call. */
+ if (self->priv->fd == -1)
+ return;
+
+ setgid_io_unlock (self->priv->fd);
+
+ setgid_io_close (self->priv->fd);
+ self->priv->fd = -1;
+}
+
+#endif /* ENABLE_SETGID */
/**
* games_scores_backend_get_scores:
@@ -117,17 +175,178 @@ games_scores_backend_new (GamesScoreStyle style,
GList *
games_scores_backend_get_scores (GamesScoresBackend * self)
{
+#ifdef ENABLE_SETGID
+ gchar *buffer;
+ gchar *eol;
+ gchar *scorestr;
+ gchar *timestr;
+ gchar *namestr;
+ GamesScore *newscore;
+ struct stat info;
+ int error;
+ ssize_t length, target;
+ GList *t;
+
+ /* Check for a change in the scores file and update if necessary. */
+ error = setgid_io_stat (self->priv->filename, &info);
+
+ /* If an error occurs then we give up on the file and return NULL. */
+ if (error != 0)
+ return NULL;
+
+ if ((info.st_mtime > self->priv->timestamp) || (self->priv->scores_list == NULL)) {
+ self->priv->timestamp = info.st_mtime;
+
+ /* Dump the old list of scores. */
+ t = self->priv->scores_list;
+ while (t != NULL) {
+ g_object_unref (t->data);
+ t = g_list_next (t);
+ }
+ g_list_free (self->priv->scores_list);
+ self->priv->scores_list = NULL;
+
+ /* Lock the file and get the list. */
+ if (!games_scores_backend_get_lock (self))
+ return NULL;
+
+ buffer = g_malloc (info.st_size + 1);
+ if (buffer == NULL) {
+ games_scores_backend_release_lock (self);
+ return NULL;
+ }
+
+ target = info.st_size;
+ length = 0;
+ do {
+ target -= length;
+ length = setgid_io_read (self->priv->fd, buffer, info.st_size);
+ if (length == -1) {
+ games_scores_backend_release_lock (self);
+ g_free (buffer);
+ return NULL;
+ }
+ } while (length < target);
+
+ buffer[info.st_size] = '\0';
+
+ /* FIXME: These details should be in a sub-class. */
+
+ /* Parse the list. We start by breaking it into lines. */
+ /* Since the buffer is null-terminated
+ * we can do the string stuff reasonably safely. */
+ eol = strchr (buffer, '\n');
+ scorestr = buffer;
+ while (eol != NULL) {
+ *eol++ = '\0';
+ timestr = strchr (scorestr, ' ');
+ if (timestr == NULL)
+ break;
+ *timestr++ = '\0';
+ namestr = strchr (timestr, ' ');
+ if (namestr == NULL)
+ break;
+ *namestr++ = '\0';
+ /* At this point we have three strings, all null terminated. All
+ * part of the original buffer. */
+ switch (self->priv->style) {
+ case GAMES_SCORES_STYLE_PLAIN_DESCENDING:
+ case GAMES_SCORES_STYLE_PLAIN_ASCENDING:
+ newscore = games_score_new_plain (g_ascii_strtod (scorestr, NULL));
+ break;
+ case GAMES_SCORES_STYLE_TIME_DESCENDING:
+ case GAMES_SCORES_STYLE_TIME_ASCENDING:
+ newscore = games_score_new_time (g_ascii_strtod (scorestr, NULL));
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+ games_score_set_name (newscore, namestr);
+ games_score_set_time (newscore, g_ascii_strtoull (timestr, NULL, 10));
+ self->priv->scores_list = g_list_append (self->priv->scores_list, newscore);
+ /* Setup again for the next time around. */
+ scorestr = eol;
+ eol = strchr (eol, '\n');
+ }
+
+ g_free (buffer);
+ }
+
+ /* FIXME: Sort the scores! We shouldn't rely on the file being sorted. */
+
+ return self->priv->scores_list;
+#else
return NULL;
+#endif /* ENABLE_SETGID */
}
gboolean
games_scores_backend_set_scores (GamesScoresBackend * self, GList * list)
{
+#ifdef ENABLE_SETGID
+ GList *s;
+ GamesScore *d;
+ gchar *buffer;
+ gint output_length = 0;
+ gchar dtostrbuf[G_ASCII_DTOSTR_BUF_SIZE];
+
+ if (!games_scores_backend_get_lock (self))
+ return FALSE;
+
+ self->priv->scores_list = list;
+
+ s = list;
+ while (s != NULL) {
+ gdouble rscore;
+ guint64 rtime;
+ const gchar *rname;
+
+ d = (GamesScore *) s->data;
+ rscore = 0.0;
+ switch (self->priv->style) {
+ case GAMES_SCORES_STYLE_PLAIN_DESCENDING:
+ case GAMES_SCORES_STYLE_PLAIN_ASCENDING:
+ rscore = games_score_get_value_as_plain (d);
+ break;
+ case GAMES_SCORES_STYLE_TIME_DESCENDING:
+ case GAMES_SCORES_STYLE_TIME_ASCENDING:
+ rscore = games_score_get_value_as_time(d);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+ rtime = games_score_get_time (d);
+ rname = games_score_get_name(d);
+
+ buffer = g_strdup_printf ("%s %"G_GUINT64_FORMAT" %s\n",
+ g_ascii_dtostr (dtostrbuf, sizeof (dtostrbuf),
+ rscore), rtime, rname);
+ setgid_io_write (self->priv->fd, buffer, strlen (buffer));
+ output_length += strlen (buffer);
+ /* Ignore any errors and blunder on. */
+ g_free (buffer);
+
+ s = g_list_next (s);
+ }
+
+ /* Remove any content in the file that hasn't yet been overwritten. */
+ setgid_io_truncate (self->priv->fd, output_length--);
+
+ /* Update the timestamp so we don't reread the scores unnecessarily. */
+ self->priv->timestamp = time (NULL);
+
+ games_scores_backend_release_lock (self);
+
+ return TRUE;
+#else
return FALSE;
+#endif /* ENABLE_SETGID */
}
void
games_scores_backend_discard_scores (GamesScoresBackend * self)
{
-
+#ifdef ENABLE_SETGID
+ games_scores_backend_release_lock (self);
+#endif
}
diff --git a/src/games-scores-backend.h b/src/games-scores-backend.h
index c094431..131fb4b 100644
--- a/src/games-scores-backend.h
+++ b/src/games-scores-backend.h
@@ -28,6 +28,10 @@
#include "games-score.h"
+#ifdef ENABLE_SETGID
+#include "games-setgid-io.h"
+#endif
+
G_BEGIN_DECLS
#define GAMES_TYPE_SCORES_BACKEND (games_scores_backend_get_type ())
diff --git a/src/games-setgid-io.c b/src/games-setgid-io.c
new file mode 100644
index 0000000..f175c15
--- /dev/null
+++ b/src/games-setgid-io.c
@@ -0,0 +1,558 @@
+/* games-setgid-io.c : Routines to perform I/O in a seperate setgid
+ * subprocess.
+ *
+ * Copyright (C) 2005 by Callum McKenzie
+ *
+ * Time-stamp: <2006-02-15 18:55:54 callum>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* WARNING: The purpose of this code is to subvert GTK's checks
+ * against setuid/setgid code. It does this by running a separate
+ * process that retains setgid privileges while the main code drops
+ * its privileges and runs the main code. The two processes
+ * communicate by a pipe. This interface is very liberal - effectively
+ * providing the standard file i/o operations with the privileges of
+ * the original executable. This is bad security. The
+ * privileged/non-privileged interface should be one more layer out so
+ * that data passing through it can be checked more rigorously. It
+ * isn't this way because a different security mechanism was assumed
+ * during the design of the scoring system and this is the simplest way to
+ * retrofit the setgid security system.
+ *
+ * In practise security shouldn't be compromised much more than it
+ * already was. The new threat is that a compromised game could
+ * over-write (or create) any file with games privileges. In the old
+ * code this was less likely since both the game code and the
+ * privileged code would have to be compromised. In any event, if
+ * games privileges are significant in your system then you have
+ * bigger security problems than this code.
+ */
+
+/* We almost directly wrap the standard open/close/read/write/seek
+ * functions and we wrap flock in a simpler lock primitive.
+ *
+ * Each function has two forms: one half that does the actual work -
+ * suffixed with _priv - and a wrapper that is called from the
+ * insecure side which stuffs the arguments down the pipe connecting
+ * the two processes.
+ *
+ * From the point of view of the caller, these functions should behave
+ * transparently with the exception of having to call setgid_io_init
+ * () right at the beginning of the program.
+ *
+ */
+
+#include <config.h>
+
+#include <glib.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+
+#include "games-setgid-io.h"
+
+enum {
+ cmd_open = 1,
+ cmd_close,
+ cmd_read,
+ cmd_write,
+ cmd_seek,
+ cmd_lock,
+ cmd_unlock,
+ cmd_stat,
+ cmd_truncate
+} commands;
+
+/* Global state variables, the program only has one global instance of
+ this module. */
+static gboolean setgid_io_initialised = 0;
+/* These names are from the point of view of the non-setgid parent. */
+static int setgid_io_infd;
+static int setgid_io_outfd;
+static int setgid_io_child_pid;
+
+
+static void
+write_cmd (unsigned char cmd)
+{
+ int cnt;
+ cnt = write (setgid_io_outfd, &cmd, 1);
+ if (cnt != 1) {
+ g_warning ("An error occurred while writing to file");
+ }
+}
+
+
+static gboolean
+write_n_bytes (int fd, const char *buffer, int n)
+{
+ int totalcnt;
+ int cnt;
+
+ totalcnt = 0;
+ while (totalcnt < n) {
+ cnt = write (fd, buffer + totalcnt, n);
+ if (cnt == -1)
+ return FALSE;
+ totalcnt += cnt;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+read_n_bytes (int fd, char *buffer, int n)
+{
+ int totalcnt;
+ int cnt;
+
+ totalcnt = 0;
+ while (totalcnt < n) {
+ cnt = read (fd, buffer + totalcnt, n);
+ if (cnt == -1)
+ return FALSE;
+ totalcnt += cnt;
+ }
+
+ return TRUE;
+}
+
+static void
+write_int (int fd, int i)
+{
+ int cnt;
+ cnt = write (fd, &i, sizeof (int));
+ if (cnt != sizeof (int)) {
+ g_warning ("An error occurred while writing to file");
+ }
+}
+
+static int
+read_int (int fd)
+{
+ int out;
+
+ if (!read_n_bytes (fd, (char *) &out, sizeof (int)))
+ return 0;
+
+ return out;
+}
+
+static void
+write_off_t (int fd, off_t o)
+{
+ int cnt;
+ cnt = write (fd, &o, sizeof (off_t));
+ if (cnt != sizeof (off_t)) {
+ g_warning ("An error occurred while writing to file");
+ }
+}
+
+static off_t
+read_off_t (int fd)
+{
+ off_t out;
+
+ if (!read_n_bytes (fd, (char *) &out, sizeof (off_t)))
+ return 0;
+
+ return out;
+}
+
+/* Unprivileged side. */
+int
+setgid_io_open (const char *path, int flags)
+{
+ int length;
+ int fd;
+
+ write_cmd (cmd_open);
+
+ length = strlen (path) + 1;
+ write_int (setgid_io_outfd, length);
+ write_n_bytes (setgid_io_outfd, path, length);
+ write_int (setgid_io_outfd, flags);
+
+ fd = read_int (setgid_io_infd);
+
+ return fd;
+}
+
+/* Privileged side. */
+static void
+setgid_io_open_priv (int outfd, int infd)
+{
+ int length;
+ char *path;
+ int flags;
+ int newfd;
+
+ length = read_int (infd);
+ path = g_malloc (length);
+ read_n_bytes (infd, path, length);
+ flags = read_int (infd);
+
+ newfd = open (path, flags);
+
+ write_int (outfd, newfd);
+ g_free (path);
+}
+
+/* Unprivileged side. */
+int
+setgid_io_close (int fd)
+{
+ write_cmd (cmd_close);
+ write_int (setgid_io_outfd, fd);
+
+ return read_int (setgid_io_infd);
+}
+
+/* Privileged side. */
+static void
+setgid_io_close_priv (int outfd, int infd)
+{
+ int fd;
+ int result;
+
+ fd = read_int (infd);
+
+ result = close (fd);
+
+ write_int (outfd, result);
+}
+
+/* Unprivileged side. */
+int
+setgid_io_read (int fd, char *buffer, int n)
+{
+ int result;
+
+ write_cmd (cmd_read);
+ write_int (setgid_io_outfd, fd);
+ write_int (setgid_io_outfd, n);
+
+ result = read_int (setgid_io_infd);
+
+ if ((result >= 0) && (result <= n)) {
+ read_n_bytes (setgid_io_infd, buffer, result);
+ }
+
+ return result;
+}
+
+/* Privileged side. */
+static void
+setgid_io_read_priv (int outfd, int infd)
+{
+ int fd;
+ int n;
+ int result;
+ char *buffer;
+
+ fd = read_int (infd);
+ n = read_int (infd);
+
+ buffer = g_malloc (n);
+ result = read (fd, buffer, n);
+ write_int (outfd, result);
+ if ((result >= 0) && (result <= n)) {
+ write_n_bytes (outfd, buffer, result);
+ }
+ g_free (buffer);
+}
+
+/* Unprivileged side. */
+int
+setgid_io_write (int fd, const char *buffer, int n)
+{
+ write_cmd (cmd_write);
+ write_int (setgid_io_outfd, fd);
+ write_int (setgid_io_outfd, n);
+ write_n_bytes (setgid_io_outfd, buffer, n);
+
+ return read_int (setgid_io_infd);
+}
+
+/* Privileged side. */
+static void
+setgid_io_write_priv (int outfd, int infd)
+{
+ int fd;
+ int n;
+ int result;
+ char *buffer;
+
+ fd = read_int (infd);
+ n = read_int (infd);
+
+ buffer = g_malloc (n);
+ read_n_bytes (infd, buffer, n);
+
+ result = write (fd, buffer, n);
+ write_int (outfd, result);
+
+ g_free (buffer);
+}
+
+/* Unprivileged side. */
+off_t
+setgid_io_seek (int fd, off_t offset, int whence)
+{
+ write_cmd (cmd_seek);
+ write_int (setgid_io_outfd, fd);
+ write_off_t (setgid_io_outfd, offset);
+ write_int (setgid_io_outfd, whence);
+
+ return read_off_t (setgid_io_infd);
+}
+
+/* Privileged side. */
+static void
+setgid_io_seek_priv (int outfd, int infd)
+{
+ int fd;
+ off_t offset;
+ int whence;
+ off_t result;
+
+ fd = read_int (infd);
+ offset = read_off_t (infd);
+ whence = read_int (infd);
+
+ result = lseek (fd, offset, whence);
+
+ write_off_t (outfd, result);
+}
+
+/* Unprivileged side. */
+int
+setgid_io_lock (int fd)
+{
+ write_cmd (cmd_lock);
+ write_int (setgid_io_outfd, fd);
+
+ return read_int (setgid_io_infd);
+}
+
+/* Privileged side. */
+static void
+setgid_io_lock_priv (int outfd, int infd)
+{
+ int fd;
+ int result;
+ struct flock lock;
+
+ fd = read_int (infd);
+
+ lock.l_type = F_WRLCK;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = 0;
+ lock.l_len = 0;
+
+ result = fcntl (fd, F_SETLKW, &lock);
+
+ write_int (outfd, result);
+}
+
+/* Unprivileged side. */
+int
+setgid_io_unlock (int fd)
+{
+ write_cmd (cmd_unlock);
+ write_int (setgid_io_outfd, fd);
+
+ return read_int (setgid_io_infd);
+}
+
+/* Privileged side. */
+static void
+setgid_io_unlock_priv (int outfd, int infd)
+{
+ int fd;
+ int result;
+ struct flock lock;
+
+ fd = read_int (infd);
+
+ lock.l_type = F_UNLCK;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = 0;
+ lock.l_len = 0;
+
+ result = fcntl (fd, F_SETLKW, &lock);
+
+ write_int (outfd, result);
+}
+
+/* Unprivileged side. */
+int
+setgid_io_stat (char *filename, struct stat *buffer)
+{
+ int length;
+
+ write_cmd (cmd_stat);
+
+ length = strlen (filename) + 1;
+ write_int (setgid_io_outfd, length);
+ write_n_bytes (setgid_io_outfd, filename, length);
+
+ read_n_bytes (setgid_io_infd, (char *) buffer, sizeof (struct stat));
+ return read_int (setgid_io_infd);
+}
+
+/* Privileged side. */
+static void
+setgid_io_stat_priv (int outfd, int infd)
+{
+ int length;
+ char *filename;
+ int result;
+ struct stat buffer;
+
+ length = read_int (infd);
+ filename = g_malloc (length);
+ read_n_bytes (infd, filename, length);
+
+ result = stat (filename, &buffer);
+
+ write_n_bytes (outfd, (char *) &buffer, sizeof (struct stat));
+ write_int (outfd, result);
+}
+
+/* Unprivileged side. */
+int
+setgid_io_truncate (int fd, int length)
+{
+ write_cmd (cmd_truncate);
+ write_int (setgid_io_outfd, fd);
+ write_int (setgid_io_outfd, length);
+
+ return read_int (setgid_io_infd);
+}
+
+/* Privileged side. */
+static void
+setgid_io_truncate_priv (int outfd, int infd)
+{
+ int fd;
+ int length;
+ int result;
+
+ fd = read_int (infd);
+ length = read_int (infd);
+ result = ftruncate (fd, length);
+
+ write_int (outfd, result);
+}
+
+G_GNUC_NORETURN
+static void
+setgid_io_pipe_watcher (int outfd, int infd)
+{
+ fd_set watchfds;
+ char command;
+ int cnt;
+
+ FD_ZERO (&watchfds);
+ FD_SET (infd, &watchfds);
+
+ while (1) {
+ select (infd + 1, &watchfds, NULL, NULL, NULL);
+ cnt = read (infd, &command, 1);
+ if (cnt == 1) {
+ switch (command) {
+ case cmd_open:
+ setgid_io_open_priv (outfd, infd);
+ break;
+ case cmd_close:
+ setgid_io_close_priv (outfd, infd);
+ break;
+ case cmd_read:
+ setgid_io_read_priv (outfd, infd);
+ break;
+ case cmd_write:
+ setgid_io_write_priv (outfd, infd);
+ break;
+ case cmd_seek:
+ setgid_io_seek_priv (outfd, infd);
+ break;
+ case cmd_lock:
+ setgid_io_lock_priv (outfd, infd);
+ break;
+ case cmd_unlock:
+ setgid_io_unlock_priv (outfd, infd);
+ break;
+ case cmd_stat:
+ setgid_io_stat_priv (outfd, infd);
+ break;
+ case cmd_truncate:
+ setgid_io_truncate_priv (outfd, infd);
+ break;
+ default:
+ g_warning ("Invalid command to setgid_io: ignored.\n");
+ }
+ } else {
+ exit (0);
+ }
+ }
+}
+
+void
+setgid_io_init (void)
+{
+ gid_t safegid;
+ int setgid_io_inpipe[2];
+ int setgid_io_outpipe[2];
+
+ if (setgid_io_initialised)
+ return;
+
+ if (pipe (setgid_io_inpipe) != 0){
+ g_warning("Unable to create pipe");
+ }
+ if (pipe (setgid_io_outpipe) != 0){
+ g_warning("Unable to create pipe");
+ }
+
+ if ((setgid_io_child_pid = fork ()) != 0) {
+ close (setgid_io_inpipe[1]);
+ close (setgid_io_outpipe[0]);
+
+ setgid_io_infd = setgid_io_inpipe[0];
+ setgid_io_outfd = setgid_io_outpipe[1];
+
+ safegid = getgid ();
+ setregid (safegid, safegid);
+ } else {
+ close (setgid_io_inpipe[0]);
+ close (setgid_io_outpipe[1]);
+ close (STDIN_FILENO);
+
+ setgid_io_pipe_watcher (setgid_io_inpipe[1], setgid_io_outpipe[0]);
+ /* We should never, ever, reach here. */
+ g_assert_not_reached ();
+ }
+
+ setgid_io_initialised = 1;
+}
diff --git a/src/games-setgid-io.h b/src/games-setgid-io.h
new file mode 100644
index 0000000..f6fa4a0
--- /dev/null
+++ b/src/games-setgid-io.h
@@ -0,0 +1,38 @@
+/* games-setgid-io.h : Routines to perform I/O in a seperate setgid
+ * subprocess.
+ *
+ * Copyright (C) 2005 by Callum McKenzie
+ *
+ * Time-stamp: <2005-12-18 12:17:26 callum>
+ */
+
+
+#ifndef GAMES_SETGID_IO_H
+#define GAMES_SETGID_IO_H
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+void setgid_io_init (void);
+int setgid_io_open (const char *path,
+ int flags);
+int setgid_io_close (int fd);
+int setgid_io_read (int fd,
+ char *buffer,
+ int n);
+int setgid_io_write (int fd,
+ const char *buffer,
+ int n);
+off_t setgid_io_seek (int fd,
+ off_t offset,
+ int whence);
+int setgid_io_lock (int fd);
+int setgid_io_unlock (int fd);
+int setgid_io_stat (char *filename,
+ struct stat *buffer);
+int setgid_io_truncate (int fd,
+ int length);
+
+#endif /* GAMES_SETGID_IO_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]