summaryrefslogtreecommitdiff
path: root/server/src
diff options
context:
space:
mode:
authordeva <deva>2007-08-22 10:25:43 +0000
committerdeva <deva>2007-08-22 10:25:43 +0000
commit9591262f6204c31f622f57be28b3d727470e2fce (patch)
tree44d30e067bfa1ff7af21b080e8294aa76f578a09 /server/src
parent47750e70ba9171c10e32a1033b68ae2b614799fa (diff)
Dummy server created.
Diffstat (limited to 'server/src')
-rw-r--r--server/src/Makefile.am24
-rw-r--r--server/src/configuration.cc67
-rw-r--r--server/src/configuration.h88
-rw-r--r--server/src/debug.h51
-rw-r--r--server/src/exception.cc77
-rw-r--r--server/src/exception.h65
-rw-r--r--server/src/log.cc43
-rw-r--r--server/src/log.h40
-rw-r--r--server/src/pracrod.cc243
-rw-r--r--server/src/server.cc107
-rw-r--r--server/src/server.h32
-rw-r--r--server/src/tcpsocket.cc346
-rw-r--r--server/src/tcpsocket.h183
-rw-r--r--server/src/tostring.cc161
-rw-r--r--server/src/tostring.h114
15 files changed, 1641 insertions, 0 deletions
diff --git a/server/src/Makefile.am b/server/src/Makefile.am
new file mode 100644
index 0000000..2ede22d
--- /dev/null
+++ b/server/src/Makefile.am
@@ -0,0 +1,24 @@
+
+bin_PROGRAMS = pracrod
+
+pracrod_LDADD = $(LD_EFENCE) $(PQXX_LIBS) $(CONFIG_LIBS)
+
+pracrod_CXXFLAGS = $(PQXX_CXXFLAGS) $(CONFIG_CXXFLAGS)
+
+pracrod_SOURCES = \
+ pracrod.cc \
+ configuration.cc \
+ exception.cc \
+ log.cc \
+ server.cc \
+ tcpsocket.cc \
+ tostring.cc
+
+EXTRA_DIST = \
+ configuration.h \
+ debug.h \
+ exception.h \
+ log.h \
+ server.h \
+ tcpsocket.h \
+ tostring.h
diff --git a/server/src/configuration.cc b/server/src/configuration.cc
new file mode 100644
index 0000000..e6d24a9
--- /dev/null
+++ b/server/src/configuration.cc
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * configuration.cc
+ *
+ * Tue Aug 15 23:57:13 CEST 2006
+ * Copyright 2006 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of Artefact.
+ *
+ * Artefact 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.
+ *
+ * Artefact 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Artefact; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include "configuration.h"
+
+#include "debug.h"
+
+#include "tostring.h"
+
+Pentominos::Configuration::Configuration(std::string filename)
+{
+ this->filename = filename;
+
+ reload();
+}
+
+void Pentominos::Configuration::reload()
+ throw(ConfigurationException)
+{
+ try {
+ readFile(this->filename.c_str());
+ } catch(libconfig::FileIOException) {
+ throw ConfigurationException("Could not read config file: File does not exist.");
+ } catch(libconfig::ParseException &e) {
+ throw ConfigurationException(std::string("Error when parsing the config file in line ")
+ + toString(e.getLine()) + ": " + e.getError());
+ }
+}
+
+
+static Pentominos::Configuration *_config = NULL;
+
+Pentominos::Configuration *Pentominos::config()
+ throw(ConfigurationException)
+{
+ if(_config == NULL)
+ throw ConfigurationException("Configuration has not yet been set.");
+ return _config;
+}
+
+void Pentominos::initConfig(Pentominos::Configuration *config)
+{
+ _config = config;
+}
diff --git a/server/src/configuration.h b/server/src/configuration.h
new file mode 100644
index 0000000..38dd233
--- /dev/null
+++ b/server/src/configuration.h
@@ -0,0 +1,88 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * configuration.h
+ *
+ * Tue Aug 15 23:57:12 CEST 2006
+ * Copyright 2006 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of Artefact.
+ *
+ * Artefact 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.
+ *
+ * Artefact 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Artefact; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#ifndef __ARTEFACT_CONFIGURATION_H__
+#define __ARTEFACT_CONFIGURATION_H__
+
+#include <libconfig.h++>
+#include <string>
+
+#include "exception.h"
+
+namespace Pentominos {
+
+ /**
+ * This exception is thrown by Configuration when reload fails.
+ */
+ class ConfigurationException: public Pentominos::Exception {
+ public:
+ ConfigurationException(std::string reason) :
+ Pentominos::Exception(reason) {}
+ };
+
+ /**
+ * This is the pentominos configuration class.\n
+ * It simply wraps the libconfig c++ interface. It can be found at
+ * http://www.hyperrealm.com/libconfig/libconfig.html\n
+ * To find out how the interface works, see
+ * http://www.hyperrealm.com/libconfig/libconfig_manual.html#The-C_002b_002b-API
+ */
+ class Configuration : public libconfig::Config {
+ public:
+ /**
+ * Constructor.\n
+ * @param filename The filename to be loaded.
+ */
+ Configuration(std::string filename);
+
+ /**
+ * reload, simply reloads the configuration file attached to the configuration
+ * object.
+ */
+ void reload() throw(ConfigurationException);
+
+ private:
+ std::string filename;
+ };
+
+ /**
+ * Initialize the global configuration.\n
+ * This function sets the Configuration global pointer, that can be reaced through
+ * the Pentominos::config variable.
+ * @param config The value of the Configuration pointer.
+ */
+ void initConfig(Configuration *config);
+
+ /**
+ * This function returns the global configuration object pointer.\n
+ * Use Pentominos::initConfig to set it.\n
+ * @return The pointer to the global configuration.
+ */
+ Configuration *config()
+ throw(ConfigurationException);
+};
+
+#endif/*__ARTEFACT_CONFIGURATION_H__*/
diff --git a/server/src/debug.h b/server/src/debug.h
new file mode 100644
index 0000000..9c49f67
--- /dev/null
+++ b/server/src/debug.h
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * debug.h
+ *
+ * Tue Mar 27 11:06:45 CEST 2007
+ * Copyright 2006 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of Artefact.
+ *
+ * Artefact 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.
+ *
+ * Artefact 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Artefact; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#ifndef __ARTEFACT_DEBUG_H__
+#define __ARTEFACT_DEBUG_H__
+
+#ifdef HAVE_CONFIG
+// For USE_EFENCE
+#include <config.h>
+#ifdef USE_EFENCE
+#include <new>
+#include <stdlib.h>
+#include <efencepp.h>
+#include <efence.h>
+
+// Lazy static alocations makes efence freak out.
+// Use this to use hardcoded values instead.
+// Currently it disables:
+// - gethostbyname
+// - getsockname
+// - getpeername
+// - iconv
+//#define BYPASS_STATICALLOCATIONS
+
+#endif/*USE_EFENCE*/
+#endif/*HAVE_CONFIG*/
+
+#endif/*__ARTEFACT_DEBUG_H__*/
diff --git a/server/src/exception.cc b/server/src/exception.cc
new file mode 100644
index 0000000..3e3bd46
--- /dev/null
+++ b/server/src/exception.cc
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * exception.cc
+ *
+ * Mon Mar 19 11:33:15 CET 2007
+ * Copyright 2006 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of Artefact.
+ *
+ * Artefact 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.
+ *
+ * Artefact 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Artefact; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include "exception.h"
+
+#include "debug.h"
+
+#include "log.h"
+
+Pentominos::Exception::Exception(std::string what)
+{
+ Pentominos::log(what);
+ _what = what;
+
+}
+
+const char* Pentominos::Exception::what() const throw()
+{
+ return _what.c_str();
+}
+
+
+#ifdef TEST_EXCEPTION
+
+class MyException : public Pentominos::Exception {
+public:
+ MyException() :
+ Pentominos::Exception("MyException has been thrown") {}
+};
+
+class MyExtException : public Pentominos::Exception {
+public:
+ MyExtException(std::string thingy) :
+ Pentominos::Exception("MyExtException has been thrown: " + thingy) {}
+};
+
+int main()
+{
+ try {
+ throw MyException();
+ } catch( MyException &e ) {
+ printf("%s\n", e.what());
+ }
+
+ try {
+ throw MyExtException("Yeaaah!");
+ } catch( MyExtException &e ) {
+ printf("%s\n", e.what());
+ }
+
+ return 0;
+}
+
+#endif/*TEST_EXCEPTION*/
diff --git a/server/src/exception.h b/server/src/exception.h
new file mode 100644
index 0000000..4a0ce23
--- /dev/null
+++ b/server/src/exception.h
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * exception.h
+ *
+ * Mon Mar 19 11:22:22 CET 2007
+ * Copyright 2006 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of Artefact.
+ *
+ * Artefact 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.
+ *
+ * Artefact 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Artefact; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#ifndef __ARTEFACT_EXCEPTION_H__
+#define __ARTEFACT_EXCEPTION_H__
+
+#include <exception>
+
+#include <string>
+
+namespace Pentominos {
+
+ /**
+ * Exception is the base class for all Pentominos exceptions
+ */
+ class Exception : public std::exception {
+ public:
+ /**
+ * The constuctor sets the error message (retained by the what() call) and
+ * adds an entry to the syslog, using the Pentominos::log interface.
+ */
+ Exception(std::string what);
+
+ /**
+ * Destructor
+ */
+ virtual ~Exception() throw() {}
+
+ /**
+ * what is used to gain textual information about the exception.
+ * @return A const char pointer to a zero terminated string containing
+ * textual information about the exception.
+ */
+ virtual const char* what() const throw();
+
+ private:
+ std::string _what;
+ };
+
+};
+
+#endif/*__ARTEFACT_EXCEPTION_H__*/
diff --git a/server/src/log.cc b/server/src/log.cc
new file mode 100644
index 0000000..384077b
--- /dev/null
+++ b/server/src/log.cc
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * log.cc
+ *
+ * Tue Oct 24 17:44:47 CEST 2006
+ * Copyright 2006 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of Artefact.
+ *
+ * Artefact 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.
+ *
+ * Artefact 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Artefact; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include "log.h"
+
+#include "debug.h"
+
+#include <syslog.h>
+
+/*
+ void openlog(const char *ident, int option, int facility); // Optional
+ void syslog(int priority, const char *format, ...);
+ void closelog(void); // Optional
+*/
+
+void Pentominos::log(std::string message)
+{
+ syslog(LOG_CONS, // Write to console if error sending to system logger.
+ message.c_str());
+}
diff --git a/server/src/log.h b/server/src/log.h
new file mode 100644
index 0000000..e1c1be0
--- /dev/null
+++ b/server/src/log.h
@@ -0,0 +1,40 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * log.h
+ *
+ * Tue Oct 24 17:44:46 CEST 2006
+ * Copyright 2006 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of Artefact.
+ *
+ * Artefact 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.
+ *
+ * Artefact 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Artefact; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#ifndef __ARTEFACT_LOG_H__
+#define __ARTEFACT_LOG_H__
+
+#include <string>
+
+namespace Pentominos {
+ /**
+ * log appends a message to the syslog queue.\n
+ * @param message An STL string containing the string to be appended.
+ */
+ void log(std::string message);
+};
+
+#endif/*__ARTEFACT_LOG_H__*/
diff --git a/server/src/pracrod.cc b/server/src/pracrod.cc
new file mode 100644
index 0000000..c9fa58b
--- /dev/null
+++ b/server/src/pracrod.cc
@@ -0,0 +1,243 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * pracrod.cc
+ *
+ * Wed Aug 22 12:15:59 CEST 2007
+ * Copyright 2007 Bent Bisballe Nyeng, Lars Bisballe Jensen and Peter Skaarup
+ * deva@aasimon.org, elsenator@gmail.com and piparum@piparum.dk
+ ****************************************************************************/
+
+/*
+ * This file is part of Pracro.
+ *
+ * Pracro 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.
+ *
+ * Pracro 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Pracro; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+// For ETC
+#include <config.h>
+
+// For setuid and setgid
+#include <sys/types.h>
+#include <unistd.h>
+
+// For signal
+#include <signal.h>
+
+// For errno and strerror
+#include <errno.h>
+
+#include <stdio.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+// For getpwent and getgrent
+#include <sys/types.h>
+#include <grp.h>
+#include <pwd.h>
+
+// For getopt_long and friends
+#include <getopt.h>
+
+#include "configuration.h"
+
+#include "server.h"
+
+#include "tcpsocket.h"
+
+static const char version_str[] =
+"Pracro server v" VERSION "\n"
+;
+
+static const char copyright_str[] =
+"Copyright (C) 2006-2007 Bent Bisballe Nyeng - Aasimon.org.\n"
+"This is free software. You may redistribute copies of it under the terms of\n"
+"the GNU General Public License <http://www.gnu.org/licenses/gpl.html>.\n"
+"There is NO WARRANTY, to the extent permitted by law.\n"
+"\n"
+"Written by Bent Bisballe Nyeng (deva@aasimon.org)\n"
+;
+
+static const char usage_str[] =
+"Usage: %s [options]\n"
+"Options:\n"
+" -c, --config file Read configfile from 'file'\n"
+" -f, --foreground Run in foreground mode (non-background mode)\n"
+" -u, --user user Run as 'user' (overrides the configfile)\n"
+" -g, --group group Run as 'group' (overrides the configfile)\n"
+" -v, --version Print version information and exit.\n"
+" -h, --help Print this message and exit.\n"
+;
+
+void reload(int fisk)
+{
+ int port;
+ printf("Reload!\n");
+ port = Pentominos::config()->lookup("port");
+ Pentominos::config()->reload();
+
+ { // Force wake the server process for reinitialization.
+ Pentominos::TCPSocket socket;
+ socket.connect("localhost", port);
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ int c;
+ char *configfile = NULL;
+ char *user = NULL;
+ char *group = NULL;
+ bool foreground = false;
+
+ int option_index = 0;
+ while(1) {
+ int this_option_optind = optind ? optind : 1;
+ static struct option long_options[] = {
+ {"foreground", no_argument, 0, 'f'},
+ {"config", required_argument, 0, 'c'},
+ {"user", required_argument, 0, 'u'},
+ {"group", required_argument, 0, 'g'},
+ {"help", no_argument, 0, 'h'},
+ {"version", no_argument, 0, 'v'},
+ {0, 0, 0, 0}
+ };
+
+ c = getopt_long (argc, argv, "hvfc:u:g:", long_options, &option_index);
+
+ if (c == -1)
+ break;
+
+ switch(c) {
+ case 'c':
+ configfile = strdup(optarg);
+ break;
+
+ case 'f':
+ foreground = true;
+ break;
+
+ case 'u':
+ user = strdup(optarg);
+ break;
+
+ case 'g':
+ group = strdup(optarg);
+ break;
+
+ case '?':
+ case 'h':
+ printf(version_str);
+ printf(usage_str, argv[0]);
+ return 0;
+
+ case 'v':
+ printf(version_str);
+ printf(copyright_str);
+ return 0;
+
+ default:
+ break;
+ }
+ }
+
+ char *cfname = NULL;
+ if(!configfile) cfname = ETC"/pracrod.conf";
+ else cfname = configfile;
+ Pentominos::Configuration conf(cfname);
+ Pentominos::initConfig(&conf);
+
+ if(!user) {
+ std::string userstr;
+ try {
+ userstr = (std::string)Pentominos::config()->lookup("user");
+ user = strdup(userstr.c_str());
+ } catch( ... ) {
+ printf("User not found in config.\n");
+ }
+ }
+
+ if(user) {
+ // Fetch user id
+ int uid = -1;
+ struct passwd *p = getpwent();
+ while(p) {
+ if(strcmp(p->pw_name, user) == 0) uid = p->pw_uid;
+ p = getpwent();
+ }
+ if(uid == -1) {
+ fprintf(stderr, "Could not find user \"%s\" in /etc/passwd file.\n", user);
+ return 1;
+ }
+
+ if(setuid(uid) == -1) {
+ fprintf(stderr, "Could not switch to user %s: %s\n", user, strerror(errno));
+ return 1;
+ }
+ }
+
+ if(!group) {
+ std::string groupstr;
+ try {
+ groupstr = (std::string)Pentominos::config()->lookup("group");
+ group = strdup(groupstr.c_str());
+ } catch( ... ) {
+ printf("Group not found in config.\n");
+ }
+
+ }
+
+ if(group) {
+ // Fetch group id
+ int gid = -1;
+ struct group *g = getgrent();
+ while(g) {
+ if(strcmp(g->gr_name, group) == 0) gid = g->gr_gid;
+ g = getgrent();
+ }
+ if(gid == -1) {
+ fprintf(stderr, "Could not find group \"%s\" in /etc/group file.\n", group);
+ return 1;
+ }
+
+ if(setgid(gid) == -1) {
+ fprintf(stderr, "Could not switch to group %s: %s\n", group, strerror(errno));
+ return 1;
+ }
+ }
+
+ if(!foreground) {
+ daemon(0,0);
+ signal (SIGTERM, SIG_IGN);
+ signal (SIGINT, SIG_IGN);
+ } else {
+ printf("Running in foreground mode.\n");
+ }
+
+ // Create callback to reload conf files.
+ signal (SIGHUP, reload);
+
+ signal(SIGCLD, SIG_IGN); // Ved SIGCHILD til IGNORE maa wait/waitpid ikke kaldes
+ // (ellers kommer der kernel-brok)
+
+ // Activate the server main loop.
+ server();
+
+ // Clean up
+ if(configfile) free(configfile);
+ if(user) free(user);
+ if(group) free(group);
+
+ return 0;
+}
diff --git a/server/src/server.cc b/server/src/server.cc
new file mode 100644
index 0000000..7f78f45
--- /dev/null
+++ b/server/src/server.cc
@@ -0,0 +1,107 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * server.cc
+ *
+ * Wed Aug 22 12:16:03 CEST 2007
+ * Copyright 2007 Bent Bisballe Nyeng, Lars Bisballe Jensen and Peter Skaarup
+ * deva@aasimon.org, elsenator@gmail.com and piparum@piparum.dk
+ ****************************************************************************/
+
+/*
+ * This file is part of Pracro.
+ *
+ * Pracro 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.
+ *
+ * Pracro 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Pracro; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include "server.h"
+
+#include "tcpsocket.h"
+#include <errno.h>
+
+#include <stdlib.h>
+
+// For fork
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "configuration.h"
+
+static void connection(Pentominos::TCPSocket &socket)
+{
+ printf("Got connection...\n");
+}
+
+void server()
+{
+ int port;
+ try {
+ port = Pentominos::config()->lookup("port");
+ } catch( ... ) {
+ fprintf(stderr, "Could not read port.");
+ return;
+ }
+
+ Pentominos::TCPSocket *socket;
+
+ try {
+ socket = new Pentominos::TCPSocket();
+ socket->listen(port);
+ } catch (Pentominos::Exception &e) {
+ fprintf(stderr, "Error during parsing:\n%s\n",
+ e.what());
+ delete socket;
+ return;
+ }
+
+ while(socket->connected()) {
+
+ { // Reload if new port i assigned.
+ int old_port = port;
+ try {
+ port = Pentominos::config()->lookup("port");
+ } catch( ... ) {
+ fprintf(stderr, "Could not read port.");
+ return;
+ }
+
+ if(port != old_port) {
+ // Start listening on the new port
+ delete socket;
+ socket = new Pentominos::TCPSocket();
+ socket->listen(port);
+ }
+ }
+
+ Pentominos::TCPSocket child = socket->accept();
+ if(child.connected()) {
+ switch(fork()) {
+ case -1: // error
+ fprintf(stderr, "Could not fork: %s\n", strerror(errno));
+ break;
+
+ case 0: // child
+ socket->disconnect();
+ connection(child);
+ delete socket;
+ return;
+
+ default: // parent
+ break;
+ }
+ }
+ }
+
+ delete socket;
+ fprintf(stderr, "Oups... dropped out of the main loop\n");
+}
diff --git a/server/src/server.h b/server/src/server.h
new file mode 100644
index 0000000..78f5ed3
--- /dev/null
+++ b/server/src/server.h
@@ -0,0 +1,32 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * server.h
+ *
+ * Wed Aug 22 12:16:03 CEST 2007
+ * Copyright 2007 Bent Bisballe Nyeng, Lars Bisballe Jensen and Peter Skaarup
+ * deva@aasimon.org, elsenator@gmail.com and piparum@piparum.dk
+ ****************************************************************************/
+
+/*
+ * This file is part of Pracro.
+ *
+ * Pracro 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.
+ *
+ * Pracro 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Pracro; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#ifndef __PRACRO_SERVER_H__
+#define __PRACRO_SERVER_H__
+
+void server();
+
+#endif/*__PRACRO_SERVER_H__*/
diff --git a/server/src/tcpsocket.cc b/server/src/tcpsocket.cc
new file mode 100644
index 0000000..19470fe
--- /dev/null
+++ b/server/src/tcpsocket.cc
@@ -0,0 +1,346 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * tcpsocket.cc
+ *
+ * Thu Oct 19 10:24:25 CEST 2006
+ * Copyright 2006 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of Artefact.
+ *
+ * Artefact 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.
+ *
+ * Artefact 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Artefact; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include "tcpsocket.h"
+
+#include "debug.h"
+
+#include "tostring.h"
+
+// for gethostbyname
+#include <netdb.h>
+
+// for inet_addr
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+// for connect, listen, bind and accept
+#include <sys/types.h>
+#include <sys/socket.h>
+
+// For socket
+#include <sys/types.h>
+#include <sys/socket.h>
+
+// For TCP
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+// For inet_ntoa
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+// For close
+#include <unistd.h>
+
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+
+// For ioctl
+#include <sys/ioctl.h>
+
+// For socket and friends
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <netinet/in.h>
+
+// For fcntl
+#include <unistd.h>
+#include <fcntl.h>
+
+Pentominos::TCPSocket::TCPSocket()
+ throw(TCPSocketException)
+{
+ if((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
+ throw TCPSocketException(strerror(errno));
+ }
+ isconnected = false;
+}
+
+Pentominos::TCPSocket::~TCPSocket()
+{
+ disconnect();
+}
+
+
+static int _listen(int sockfd, int backlog){return listen(sockfd, backlog);}
+void Pentominos::TCPSocket::listen(unsigned short int port)
+ throw(TCPListenException)
+{
+
+ if(sock == -1) {
+ throw TCPListenException("Socket not initialized.");
+ }
+
+ if(isconnected) {
+ throw TCPListenException("Socket already connected.");
+ }
+
+ struct sockaddr_in socketaddr;
+ memset((char *) &socketaddr, sizeof(socketaddr), 0);
+ socketaddr.sin_family = AF_INET;
+ socketaddr.sin_port = htons(port);
+ socketaddr.sin_addr.s_addr = htonl(INADDR_ANY);
+
+ if(bind(sock, (struct sockaddr*)&socketaddr, sizeof(socketaddr)) == -1) {
+ throw TCPListenException(std::string("bind failed - ") + strerror(errno));
+ }
+
+ if(_listen(sock, 5) == -1) {
+ throw TCPListenException(std::string("listen failed - ") + strerror(errno));
+ }
+
+ isconnected = true;
+}
+
+
+static int _accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
+{return accept(sockfd, addr, addrlen);}
+Pentominos::TCPSocket Pentominos::TCPSocket::accept()
+ throw(TCPAcceptException)
+{
+ TCPSocket child;
+
+ if(sock == -1) {
+ throw TCPAcceptException("Socket not initialized.");
+ }
+
+ if(!isconnected) {
+ throw TCPAcceptException("Socket not connected.");
+ }
+
+ // accept new connection and get its connection descriptor
+ struct sockaddr_in ssocketaddr;
+ int csalen = sizeof(ssocketaddr);
+
+ child.disconnect(); // We need to close the existing socket
+ child.sock = _accept(sock, (struct sockaddr*)&ssocketaddr, (socklen_t*)&csalen);
+
+ if (child.sock == -1) {
+ throw TCPAcceptException(std::string("accept failed - ") + strerror(errno));
+ }
+
+ child.isconnected = true;
+ return child;
+}
+
+
+static int _connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen)
+{return connect(sockfd, serv_addr, addrlen);}
+void Pentominos::TCPSocket::connect(std::string addr, unsigned short int port)
+ throw(TCPConnectException)
+
+{
+ if(isconnected) {
+ throw TCPConnectException("Socket already connected.", "", "");
+ }
+
+#ifndef BYPASS_STATICALLOCATIONS
+ // Do DNS lookup
+ char *ip;
+ struct in_addr **addr_list;
+ struct hostent *he;
+ he = gethostbyname(addr.c_str());
+ if(!he || !he->h_length) {
+ throw TCPConnectException(addr, toString(port),
+ std::string("host lookup failed: ") + hstrerror(h_errno));
+ }
+
+ addr_list = (struct in_addr **)he->h_addr_list;
+ // Get first value. We know for sure that there are at least one.
+ ip = inet_ntoa(*addr_list[0]);
+#else/*BYPASS_STATICALLOCATIONS*/
+ char *ip = "127.0.0.1";
+#endif/*BYPASS_STATICALLOCATIONS*/
+
+ struct sockaddr_in socketaddr;
+ memset((char *) &socketaddr, sizeof(socketaddr), 0);
+ socketaddr.sin_family = AF_INET;
+ socketaddr.sin_port = htons(port);
+ socketaddr.sin_addr.s_addr = inet_addr(ip);
+
+ if(_connect(sock, (struct sockaddr*)&socketaddr, sizeof(socketaddr))) {
+ throw TCPConnectException(addr, toString(port), hstrerror(h_errno));
+ }
+
+ isconnected = true;
+}
+
+void Pentominos::TCPSocket::disconnect()
+{
+ if(sock != -1) {
+ close(sock);
+ sock = -1;
+ }
+ isconnected = false;
+}
+
+bool Pentominos::TCPSocket::connected()
+{
+ return sock != -1 && isconnected;
+}
+
+int Pentominos::TCPSocket::read(char *buf, int size)
+ throw(TCPReadException)
+{
+ int res = 0;
+
+ if(sock == -1) {
+ throw TCPReadException("Socket not initialized.");
+ }
+
+ if(!isconnected) {
+ throw TCPReadException("Socket is not connected.");
+ }
+
+ /*
+ if( (res = recv(sock, buf, size, MSG_WAITALL)) == -1 ) {
+ throw TCPReadException(strerror(errno));
+ }
+ */
+
+ // Wait until something is ready to be read ( peek'a'loop ).
+ errno = EAGAIN;
+ while( recv(sock, buf, 1, MSG_PEEK) == -1 && errno == EAGAIN) {
+ sleep(1);
+ }
+
+ // Now read it
+ if( (res = recv(sock, buf, size, MSG_DONTWAIT)) == -1 ) {
+ throw TCPReadException(strerror(errno));
+ }
+
+ return res;
+}
+
+int Pentominos::TCPSocket::write(char *data, int size)
+ throw(TCPWriteException)
+{
+ if(sock == -1) {
+ throw TCPWriteException("Socket not initialized.");
+ }
+
+ if(!isconnected) {
+ throw TCPWriteException("Socket is not connected.");
+ }
+
+ int res;
+ if( (res = send(sock, data, size, MSG_WAITALL)) == -1 ) {
+ throw TCPWriteException(strerror(errno));
+ }
+
+ return res;
+}
+
+std::string Pentominos::TCPSocket::srcaddr()
+ throw(TCPNameException)
+{
+ std::string addr;
+
+#ifndef BYPASS_STATICALLOCATIONS
+ struct sockaddr_in name;
+ socklen_t namelen = sizeof(name);
+ if(getpeername(sock, (sockaddr*)&name, &namelen) == -1) {
+ throw TCPNameException(strerror(errno));
+ }
+
+ addr = inet_ntoa(name.sin_addr);
+#else/*BYPASS_STATICALLOCATIONS*/
+ addr = "127.0.0.1";
+#endif/*BYPASS_STATICALLOCATIONS*/
+
+ return addr;
+}
+
+std::string Pentominos::TCPSocket::dstaddr()
+ throw(TCPNameException)
+{
+ std::string addr;
+
+#ifndef BYPASS_STATICALLOCATIONS
+ struct sockaddr_in name;
+ socklen_t namelen = sizeof(name);
+ if(getsockname(sock, (sockaddr*)&name, &namelen) == -1) {
+ throw TCPNameException(strerror(errno));
+ }
+
+ addr = inet_ntoa(name.sin_addr);
+#else/*BYPASS_STATICALLOCATIONS*/
+ addr = "127.0.0.1";
+#endif/*BYPASS_STATICALLOCATIONS*/
+
+ return addr;
+}
+
+#ifdef TEST_TCPSOCKET
+
+int main()
+{
+ char buf[32];
+
+ switch(fork()) {
+ case -1: // error
+ fprintf(stderr, "Could not fork: %s\n", strerror(errno));
+ return 1;
+
+ case 0: // child
+ try {
+ Pentominos::TCPSocket client;
+ sleep(1); // We need to wait for the listen socket to be created.
+ client.connect("localhost", 12345);
+ sprintf(buf, "hello");
+ client.write(buf, sizeof(buf));
+ printf("Sent: [%s]\n", buf);
+ } catch( Pentominos::Exception &e ) {
+ fprintf(stderr, "%s\n", e.what());
+ return 1;
+ }
+ break;
+
+ default: // parent
+ try {
+ Pentominos::TCPSocket listen_sock;
+ listen_sock.listen(12345);
+ Pentominos::TCPSocket sock = listen_sock.accept();
+ sock.read(buf, sizeof(buf));
+ printf("Got: [%s]\n", buf);
+ if(std::string(buf) != "hello") return 1;
+ } catch( Pentominos::Exception &e ) {
+ fprintf(stderr, "%s\n", e.what());
+ return 1;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+#endif/*TEST_TCPSOCKET*/
diff --git a/server/src/tcpsocket.h b/server/src/tcpsocket.h
new file mode 100644
index 0000000..f392a2c
--- /dev/null
+++ b/server/src/tcpsocket.h
@@ -0,0 +1,183 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * tcpsocket.h
+ *
+ * Thu Oct 19 10:24:25 CEST 2006
+ * Copyright 2006 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of Artefact.
+ *
+ * Artefact 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.
+ *
+ * Artefact 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Artefact; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#ifndef __ARTEFACT_TCPSOCKET_H__
+#define __ARTEFACT_TCPSOCKET_H__
+
+#include <string>
+
+#include "exception.h"
+
+namespace Pentominos {
+
+ /**
+ * This exception is thrown by TCPSocket when the socket creation fails.
+ */
+ class TCPSocketException: public Pentominos::Exception {
+ public:
+ TCPSocketException(std::string reason) :
+ Pentominos::Exception("Could not create socket: " + reason) {}
+ };
+
+ /**
+ * This exception is thrown by TCPSocket when listen fails.
+ */
+ class TCPListenException: public Pentominos::Exception {
+ public:
+ TCPListenException(std::string reason) :
+ Pentominos::Exception("Listen failed: " + reason) {}
+ };
+
+ /**
+ * This exception is thrown by TCPSocket when accept fails.
+ */
+ class TCPAcceptException: public Pentominos::Exception {
+ public:
+ TCPAcceptException(std::string reason) :
+ Pentominos::Exception("Accept failed: " + reason) {}
+ };
+
+ /**
+ * This exception is thrown by TCPSocket when connection fails.
+ */
+ class TCPConnectException: public Pentominos::Exception {
+ public:
+ TCPConnectException(std::string host, std::string port, std::string reason) :
+ Pentominos::Exception("Could not connect to " + host + ":" + port + ": " + reason) {}
+ };
+
+ /**
+ * This exception is thrown by TCPSocket when reading fails.
+ */
+ class TCPReadException: public Pentominos::Exception {
+ public:
+ TCPReadException(std::string reason) :
+ Pentominos::Exception("TCPSocket could not read data: " + reason) {}
+ };
+
+ /**
+ * This exception is thrown by TCPSocket when writing fails.
+ */
+ class TCPWriteException: public Pentominos::Exception {
+ public:
+ TCPWriteException(std::string reason) :
+ Pentominos::Exception("TCPSocket could not write data: " + reason) {}
+ };
+
+ /**
+ * This exception is thrown by TCPSocket when there is an error in name lookup.
+ */
+ class TCPNameException: public Pentominos::Exception {
+ public:
+ TCPNameException(std::string reason) :
+ Pentominos::Exception("TCPSocket could not get name: " + reason) {}
+ };
+
+ /**
+ * This class is used to commumicate through a TCP/IP connection, wether it
+ * is a server (listening) or a client (transmitting).
+ */
+ class TCPSocket {
+ public:
+ /**
+ * Constructor. Creates a new tcp socket.
+ */
+ TCPSocket() throw(TCPSocketException);
+
+ /**
+ * Destructor. Closes the tcp socket.
+ */
+ ~TCPSocket();
+
+ /**
+ * Sets the socket in listen mode.\n
+ * @param port The port number on which to listen.
+ */
+ void listen(unsigned short int port) throw(TCPListenException);
+
+ /**
+ * Accept an incoming connection.\n
+ * The call is blocking and returns only when an incoming connection is received.\n
+ * The socket must be in listen mode in order for this call to work.\n
+ * Multiple accepts can be made on the same listening socket.
+ * @return A connected TCPSocket ready to communicate.
+ */
+ TCPSocket accept() throw(TCPAcceptException);
+
+ /**
+ * Connects to a host for data transmission.
+ * @param addr The address of the host to connect to.
+ * @param port The portnumber of the host to connect to.
+ */
+ void connect(std::string addr, unsigned short int port) throw(TCPConnectException);
+
+ /**
+ * Disconnect the socket.
+ */
+ void disconnect();
+
+ /**
+ * Tells whether the socket is connected or not.
+ * @return true if the socket is connected, false if not.
+ */
+ bool connected();
+
+ /**
+ * Reads bytes from the socket into a buffer.
+ * @param buf The buffer into which the data will be written.
+ * @param size The maximum number of bytes to read in (the size of the buffer).
+ * @return The actual number of bytes read.
+ */
+ int read(char *buf, int size) throw(TCPReadException);
+
+ /**
+ * Writes bytes from a buffer to the socket.
+ * @param data The buffer from which the data will be read.
+ * @param size The number of bytes to write.
+ * @return The actual number of bytes written.
+ */
+ int write(char *data, int size) throw(TCPWriteException);
+
+ /**
+ * Get the source address of the socket (IP address not DNS name).
+ * @return An STL string containing the source address.
+ */
+ std::string srcaddr() throw(TCPNameException);
+
+ /**
+ * Get the destination address of the socket (IP address not DNS name).
+ * @return An STL string containing the destination address.
+ */
+ std::string dstaddr() throw(TCPNameException);
+
+ private:
+ bool isconnected;
+ int sock;
+ };
+
+};
+
+#endif/*__ARTEFACT_TCPSOCKET_H__*/
diff --git a/server/src/tostring.cc b/server/src/tostring.cc
new file mode 100644
index 0000000..e218a32
--- /dev/null
+++ b/server/src/tostring.cc
@@ -0,0 +1,161 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * tostring.cc
+ *
+ * Thu Mar 29 13:16:13 CEST 2007
+ * Copyright 2006 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of Artefact.
+ *
+ * Artefact 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.
+ *
+ * Artefact 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Artefact; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include "tostring.h"
+
+#include "debug.h"
+
+#include <stdio.h>
+
+std::string Pentominos::toString(std::string s)
+{
+ return s;
+}
+
+std::string Pentominos::toString(char c)
+{
+ char buf[32];
+ sprintf(buf, "%c", c);
+ std::string out = buf;
+ return buf;
+}
+
+std::string Pentominos::toString(unsigned char c)
+{
+ char buf[32];
+ sprintf(buf, "%c", c);
+ std::string out = buf;
+ return buf;
+}
+
+std::string Pentominos::toString(short int si)
+{
+ char buf[32];
+ sprintf(buf, "%d", si);
+ std::string out = buf;
+ return buf;
+}
+
+std::string Pentominos::toString(short unsigned int su)
+{
+ char buf[32];
+ sprintf(buf, "%u", su);
+ std::string out = buf;
+ return buf;
+}
+
+std::string Pentominos::toString(int li)
+{
+ char buf[32];
+ sprintf(buf, "%ld", li);
+ std::string out = buf;
+ return buf;
+}
+
+std::string Pentominos::toString(unsigned int lu)
+{
+ char buf[32];
+ sprintf(buf, "%lu", lu);
+ std::string out = buf;
+ return buf;
+}
+
+std::string Pentominos::toString(bool b)
+{
+ if(b) return "true";
+ else return "false";
+}
+
+std::string Pentominos::toString(float f, unsigned int precision)
+{
+ char buf[100];
+ char format[12];
+ sprintf(format, "%%.%uf", precision);
+ sprintf(buf, format, f);
+ std::string out = buf;
+ return buf;
+ return "";
+}
+
+std::string Pentominos::toString(double d, unsigned int precision)
+{
+ char buf[100];
+ char format[12];
+ sprintf(format, "%%.%uf", precision);
+ sprintf(buf, format, d);
+ std::string out = buf;
+ return buf;
+}
+
+std::string Pentominos::toString(long double ld, unsigned int precision)
+{
+ char buf[100];
+ char format[12];
+ sprintf(format, "%%.%uLg", precision);
+ sprintf(buf, format, ld);
+ std::string out = buf;
+ return buf;
+}
+
+#ifdef TEST_TOSTRING
+/* Compile:
+ * c++ -DTEST_TOSTRING tostring.cc -o test_tostring
+ */
+using namespace Pentominos;
+
+int main()
+{
+ std::string s = "string";
+ char c = -4;
+ unsigned char uc = 'a';
+ short int si = 0x8000;
+ short unsigned int su = 0xffff;
+ long int li = 0x80000000L;
+ long unsigned int lu = 0xffffffffL;
+ bool b = true;
+ float f = 0.1;
+ double d = 0.1;
+ long double ld = 0.1;
+
+std::string str =
+ "[" + Pentominos::toString(s)
+ + "] [" + Pentominos::toString(c)
+ + "] [" + Pentominos::toString(uc)
+ + "] [" + Pentominos::toString(si)
+ + "] [" + Pentominos::toString(su)
+ // + "] [" + Pentominos::toString(li)
+ // + "] [" + Pentominos::toString(lu)
+ + "] [" + Pentominos::toString(b)
+ + "] [" + Pentominos::toString(f, 10)
+ + "] [" + Pentominos::toString(d, 18)
+ + "] [" + Pentominos::toString(ld, 36)
+ + "]";
+
+ printf("%s\n", str.c_str());
+
+ return 0;
+}
+#endif/*TEST_TOSTRING*/
diff --git a/server/src/tostring.h b/server/src/tostring.h
new file mode 100644
index 0000000..0b63fb3
--- /dev/null
+++ b/server/src/tostring.h
@@ -0,0 +1,114 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * tostring.h
+ *
+ * Thu Mar 29 13:16:13 CEST 2007
+ * Copyright 2006 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of Artefact.
+ *
+ * Artefact 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.
+ *
+ * Artefact 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Artefact; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#ifndef __ARTEFACT_TOSTRING_H__
+#define __ARTEFACT_TOSTRING_H__
+
+#include <string>
+
+namespace Pentominos {
+ /**
+ * toString converts a nonstring variable into an STL string.
+ * @param s A string, converted into a... string...
+ * @return The STL string containing the converted value.
+ */
+ std::string toString(std::string s);
+
+ /**
+ * toString converts a nonstring variable into an STL string.
+ * @param c A char, converted into a string.
+ * @return The STL string containing the converted value.
+ */
+ std::string toString(char c);
+
+ /**
+ * toString converts a nonstring variable into an STL string.
+ * @param c A unsigned char, converted into a string.
+ * @return The STL string containing the converted value.
+ */
+ std::string toString(unsigned char c);
+
+ /**
+ * toString converts a nonstring variable into an STL string.
+ * @param si A short integer, converted into a string.
+ * @return The STL string containing the converted value.
+ */
+ std::string toString(short int si);
+
+ /**
+ * toString converts a nonstring variable into an STL string.
+ * @param su An unsigned short integer, converted into a string.
+ * @return The STL string containing the converted value.
+ */
+ std::string toString(short unsigned int su);
+
+ /**
+ * toString converts a nonstring variable into an STL string.
+ * @param li A long integer, converted into a string.
+ * @return The STL string containing the converted value.
+ */
+ std::string toString(int li);
+
+ /**
+ * toString converts a nonstring variable into an STL string.
+ * @param lu An unsigned long integer, converted into a string.
+ * @return The STL string containing the converted value.
+ */
+ std::string toString(unsigned int lu);
+
+ /**
+ * toString converts a nonstring variable into an STL string.
+ * @param b A boolean value, converted into a string (true/false).
+ * @return The STL string containing the converted value.
+ */
+ std::string toString(bool b);
+
+ /**
+ * toString converts a nonstring variable into an STL string.
+ * @param f A floating point value, converted into a string.
+ * @param precision The precision to use when converting.
+ * @return The STL string containing the converted value.
+ */
+ std::string toString(float f, unsigned int precision = 8);
+
+ /**
+ * toString converts a nonstring variable into an STL string.
+ * @param d A double precision floating point value, converted into a string.
+ * @param precision The precision to use when converting.
+ * @return The STL string containing the converted value.
+ */
+ std::string toString(double d, unsigned int precision = 16);
+
+ /**
+ * toString converts a nonstring variable into an STL string.
+ * @param ld A long double precision floating point value, converted into a string.
+ * @param precision The precision to use when converting.
+ * @return The STL string containing the converted value.
+ */
+ std::string toString(long double ld, unsigned int precision = 32);
+};
+
+#endif/*__ARTEFACT_TOSTRING_H__*/