store gtkballs-scores in get_config_dir_file()

remove child.c/h and the complex logic behind storing files in /var
which usually only the root user can access
This commit is contained in:
wdlkmpx 2021-01-30 10:55:17 +08:00
parent 80c71e2330
commit 964bfccbc6
7 changed files with 19 additions and 216 deletions

View File

@ -7,7 +7,7 @@ gtkballs_SOURCES = gtkballs.c gtkballs.h gfx.c gfx.h \
path.c path.h preferences.c preferences.h \
scoreboard.c scoreboard.h themerc.c themerc.h \
gtkutils.c gtkutils.h mainmenu.c mainmenu.h \
rules.c rules.h about.c about.h child.c child.h \
rules.c rules.h about.c about.h \
theme.c theme.h savegame.c savegame.h \
savedialog.c savedialog.h halloffame.c halloffame.h \
inputname.c inputname.h rulesdialog.c rulesdialog.h \

View File

@ -1,147 +0,0 @@
/* child.c - spawn child, that works with extra privileges
* to be able to write scores.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*/
#include <glib.h>
#include <sys/time.h> /* select() */
#include <sys/types.h> /* pid_t */
#include <sys/stat.h> /* open() */
#include <fcntl.h> /* fcntl() */
#include <signal.h> /* sigaction() */
#include <unistd.h> /* pipe() */
#include <string.h> /* strerror() */
#include <errno.h> /* errno */
#include <stdlib.h> /* exit() */
#include <sys/wait.h> /* waitpid() */
#include <stdio.h> /* printf() */
volatile sig_atomic_t _child_writer_alive = 0;
gboolean _child_writer_dead_warned = 0;
int child_writer_alive(void){
return _child_writer_alive;
}
int child_writer_dead_handler(void) {
if (_child_writer_alive == 0 && _child_writer_dead_warned == 0) {
_child_writer_dead_warned = 1;
return 1;
}
return 0;
}
void child_process_score_writer(int chfd, gchar *score_file)
{
fd_set rfds;
int i;
int fd=-1;
gchar *buf;
size_t sz;
sigset_t sset;
struct flock lockinfo;
gchar *score_file_full = g_strconcat(LOCALSTATEDIR, score_file, NULL);
while (1)
{
FD_ZERO(&rfds);
FD_SET(chfd, &rfds);
if (select(chfd + 1, &rfds, NULL, NULL, NULL) > 0)
{
if (read(chfd, &sz, sizeof(sz)) <= 0) {
exit(0);
}
/* block signals before writing, to prevent possible file corruption */
sigemptyset(&sset);
sigaddset(&sset, SIGHUP);
sigaddset(&sset, SIGINT);
sigaddset(&sset, SIGQUIT);
sigaddset(&sset, SIGTERM);
sigprocmask(SIG_BLOCK, &sset, NULL);
fd = open(score_file_full, O_WRONLY | O_TRUNC);
if (fd != -1) {
/* get write lock before writing scores */
lockinfo.l_whence = SEEK_SET;
lockinfo.l_start = 0;
lockinfo.l_len = 0;
i = 0;
while (1) {
lockinfo.l_type=F_WRLCK;
if (!fcntl(fd, F_SETLK, &lockinfo)) {
break;
}
if (i >= 3) {
close(fd);
fd = -1;
}
i++;
}
}
while (sz > 0) {
buf=g_malloc(sz);
read(chfd, buf, sz);
if (fd != -1) {
write(fd, buf, sz);
}
g_free(buf);
read(chfd, &sz, sizeof(sz));
}
if (fd != -1) {
close(fd);
} else {
/* FIXME: here should be some sort of error reporting to parent */
}
sigprocmask(SIG_UNBLOCK, &sset, NULL);
}
}
}
static void sigchld_handler(int param)
{
pid_t ret = waitpid(0, NULL, WNOHANG);
if (ret > 0) { /* score writer process killed by bastards! */
_child_writer_alive = 0;
}
}
int child_setup(gchar *score_file)
{
pid_t pid;
struct sigaction sact;
int sfds[2];
/* set up SIGCHLD handler, so we can know if our score writer process
terminated while we run... */
sact.sa_handler = sigchld_handler;
sigemptyset(&sact.sa_mask);
sact.sa_flags = 0;
#ifdef SA_RESTART
sact.sa_flags |= SA_RESTART;
#endif
if (sigaction(SIGCHLD, &sact, NULL) < 0) {
printf("cannot setup SIGCHLD handler.\n");
return -1;
}
if (pipe(sfds) == -1) {
printf("pipe() failed: %s\n", strerror(errno));
return -1;
}
pid = fork();
if (pid == -1) {
printf("cannot fork: %s\n", strerror(errno));
return -1;
} else if (pid == 0) {
close(sfds[1]);
child_process_score_writer(sfds[0], score_file);
}
close(sfds[0]);
_child_writer_alive = 1;
return sfds[1];
}

View File

@ -1,13 +0,0 @@
#ifndef __CHILD_H__
#define __CHILD_H__
/* spawn score writer process */
int child_setup(gchar *score_file);
/* check if child process alive or not */
int child_writer_alive(void);
/* check score writer process and display warning if not running */
int child_writer_dead_handler(void);
#endif

View File

@ -16,7 +16,6 @@
#include "prefs.h" /* preferences */
#include "scoreboard.h" /* read_score, score_setup */
#include "gfx.h"
#include "child.h"
#include "theme.h"
#include "inputname.h" /* input_name_dialog */
#include "game.h"
@ -155,11 +154,6 @@ int main(int argc, char **argv)
bind_textdomain_codeset(PACKAGE, "UTF8");
#endif /* ENABLE_NLS */
/* drop privileges after spawning child with extra privs */
if (score_setup() == -1)
return 1;
setregid(getgid(), getgid());
/* initialize random seed */
gettimeofday(&tv, &tz);
srand((unsigned int)tv.tv_usec);
@ -201,9 +195,7 @@ int main(int argc, char **argv)
remake_board(-1, 1);
/* read and set scores */
if (!read_score(scoreboard, NULL, NULL)) {
ut_simple_message_box(_("Unable to read score.\n"));
}
read_score (scoreboard, NULL, NULL);
mw_set_hi_score(scoreboard[0].score);
mw_set_user_score(0);

View File

@ -14,7 +14,6 @@
#include "gtkutils.h"
#include "mainmenu.h" /* menu_* */
#include "game.h"
#include "child.h"
GtkWindow * main_window;
@ -78,12 +77,6 @@ gboolean _countdown_timer(gpointer data)
GtkLabel *label = data;
gint trem;
if (child_writer_dead_handler()) {
ut_simple_message_box_with_title(_("Score writer process died unexpectedly. No scores will be writen!\n" \
"Save your game and restart programm.\n"),
_("Who Killed Bambi?"));
}
if (!timer_is_running()) {
gtk_label_set_text(label, _("Time is unlimited"));
return TRUE;

View File

@ -16,19 +16,11 @@
#include "gtkballs.h"
#include "scoreboard.h"
#include "child.h" /* child_writer_alive, child_setup */
#include "game.h"
#define SCORE_FILE "gtkballs-scores"
#define BUFFER_SIZE 1024
int _score_fd = -1;
gint score_setup(void)
{
_score_fd = child_setup(SCORE_FILE);
return _score_fd;
}
void free_score_board_full(struct score_board_full *bf, gint nbf)
{
@ -44,10 +36,13 @@ void free_score_board_full(struct score_board_full *bf, gint nbf)
gint write_score(struct score_board *b, struct score_board_full *bf, gint nbf)
{
gint i;
gchar *buf, *tname, *tdate, *rules;
size_t sz;
gchar *tname, *tdate, *rules;
char * score_file = get_config_dir_file (SCORE_FILE);
FILE * fd;
if (child_writer_alive() == 0) {
fd = fopen (score_file, "w");
if (!fd) {
g_free (score_file);
return FALSE;
}
@ -63,27 +58,19 @@ gint write_score(struct score_board *b, struct score_board_full *bf, gint nbf)
tdate = g_strdup(_("Unknown"));
}
rules = rules_get_as_str();
buf = g_strdup_printf("%s\t%i\t%s\t%s\n", tname, b[i].score, tdate, rules);
sz = strlen(buf);
write(_score_fd, &sz, sizeof(sz));
write(_score_fd, buf, strlen(buf));
fprintf (fd, "%s\t%i\t%s\t%s\n", tname, b[i].score, tdate, rules);
g_free(rules);
g_free(tdate);
g_free(tname);
g_free(buf);
}
}
for (i = 0; i < nbf; i++) {
if (strlen(bf[i].name)) {
buf = g_strdup_printf("%s\t%i\t%s\t%s\n", bf[i].name, bf[i].score, bf[i].date, bf[i].rules);
sz = strlen(buf);
write(_score_fd, &sz, sizeof(sz));
write(_score_fd, buf, strlen(buf));
g_free(buf);
fprintf (fd, "%s\t%i\t%s\t%s\n", bf[i].name, bf[i].score, bf[i].date, bf[i].rules);
}
}
sz = 0;
write(_score_fd, &sz, sizeof(sz));
g_free (score_file);
fclose (fd);
return TRUE;
}
@ -104,24 +91,17 @@ gint read_score(struct score_board *b, struct score_board_full **bf, gint *nbf)
gchar **str_val, *tstr, **tstr_val;
gint valid, sc, fsc;
gsize br, bw;
struct flock lockinfo;
char * score_file = get_config_dir_file (SCORE_FILE);
gchar *g_rules = NULL;
memset(b, 0, sizeof(struct score_board) * 10);
if (!(fp = fopen(LOCALSTATEDIR SCORE_FILE, "r"))) {
return FALSE;
if (!(fp = fopen(score_file, "r"))) {
g_free (score_file);
return TRUE;
}
do {
lockinfo.l_whence = SEEK_SET;
lockinfo.l_start = 0;
lockinfo.l_len = 0;
lockinfo.l_type = F_WRLCK;
fcntl(fileno(fp), F_GETLK, &lockinfo);
} while (lockinfo.l_type != F_UNLCK);
sc = 0;
fsc = 0;
while (fgets(buffer, BUFFER_SIZE, fp))
@ -198,6 +178,8 @@ gint read_score(struct score_board *b, struct score_board_full **bf, gint *nbf)
}
g_strfreev(str_val);
}
g_free (score_file);
fclose(fp);
qsort(b, 10, sizeof(struct score_board), score_sort);

View File

@ -1,8 +1,6 @@
#ifndef __SCOREBOARD_H__
#define __SCOREBOARD_H__
#define SCORE_FILE "/gtkballs-scores"
struct score_board {
gchar name[30];
gint score;
@ -16,8 +14,6 @@ struct score_board_full {
gchar *rules;
};
gint score_setup(void);
void free_score_board_full(struct score_board_full *bf, gint nbf);
gint write_score(struct score_board *, struct score_board_full *, gint);
gint read_score(struct score_board *, struct score_board_full **, gint *);