summaryrefslogtreecommitdiffstats
path: root/mcop/mcoputils.cc
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-01-05 00:01:18 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-01-05 00:01:18 +0000
commit42995d7bf396933ee60c5f89c354ea89cf13df0d (patch)
treecfdcea0ac57420e7baf570bfe435e107bb842541 /mcop/mcoputils.cc
downloadarts-42995d7bf396933ee60c5f89c354ea89cf13df0d.tar.gz
arts-42995d7bf396933ee60c5f89c354ea89cf13df0d.zip
Copy of aRts for Trinity modifications
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/dependencies/arts@1070145 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'mcop/mcoputils.cc')
-rw-r--r--mcop/mcoputils.cc574
1 files changed, 574 insertions, 0 deletions
diff --git a/mcop/mcoputils.cc b/mcop/mcoputils.cc
new file mode 100644
index 0000000..14275fb
--- /dev/null
+++ b/mcop/mcoputils.cc
@@ -0,0 +1,574 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "mcoputils.h"
+#include "mcopconfig.h"
+#include "debug.h"
+#include <pwd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <errno.h>
+#include <config.h>
+#include <ctype.h>
+#include <cstdlib>
+#include <cstring>
+#include <stdio.h>
+#include <map>
+
+using namespace std;
+using namespace Arts;
+
+// 0: Dir ok
+// 1: Dir not ok
+static int check_tmp_dir(const char *tmp_dir)
+{
+ int result;
+ struct stat stat_buf;
+ result = lstat(tmp_dir, &stat_buf);
+ if ((result == -1) && (errno == ENOENT))
+ {
+ return 1;
+ }
+ if ((result == -1) || (!S_ISDIR(stat_buf.st_mode)))
+ {
+ arts_warning("Error: \"%s\" is not a directory.\n", tmp_dir);
+ return 1;
+ }
+
+ if (stat_buf.st_uid != getuid())
+ {
+ arts_warning("Error: \"%s\" is owned by uid %d instead of uid %d.\n", tmp_dir, stat_buf.st_uid, getuid());
+ return 1;
+ }
+ return 0;
+}
+
+
+// 0: Link not ok
+// != 0: location of mcop directory
+static char *locate_mcop_dir()
+{
+ struct passwd *pw_ent;
+ char kde_tmp_dir[PATH_MAX+1];
+ char user_tmp_dir[PATH_MAX+1];
+ int uid = getuid();
+ const char *home_dir = getenv("HOME");
+ const char *kde_home = uid ? getenv("KDEHOME") : getenv("KDEROOTHOME");
+ const char *kde_prefix = "/socket-";
+ const char *tmp;
+ char *tmp_buf;
+ int result;
+ struct stat stat_buf;
+
+ tmp = getenv("KDETMP");
+ if (!tmp || !tmp[0])
+ tmp = getenv("TMPDIR");
+ if (!tmp || !tmp[0])
+ tmp = "/tmp";
+
+ kde_tmp_dir[0] = 0;
+
+ pw_ent = getpwuid(uid);
+ if (!pw_ent)
+ {
+ arts_warning("Error: Can not find password entry for uid %d.\n", getuid());
+ return 0;
+ }
+
+ strncpy(user_tmp_dir, tmp, PATH_MAX );
+ user_tmp_dir[ PATH_MAX ] = '\0';
+ strncat(user_tmp_dir, "/ksocket-", PATH_MAX - strlen(user_tmp_dir) );
+ user_tmp_dir[ PATH_MAX ] = '\0';
+ strncat(user_tmp_dir, pw_ent->pw_name, PATH_MAX - strlen(user_tmp_dir));
+ user_tmp_dir[ PATH_MAX ] = '\0';
+
+ if (!kde_home || !kde_home[0])
+ {
+ kde_home = "~/.kde/";
+ }
+
+ if (kde_home[0] == '~')
+ {
+ if (uid == 0)
+ {
+ home_dir = pw_ent->pw_dir ? pw_ent->pw_dir : "/root";
+ }
+ if (!home_dir || !home_dir[0])
+ {
+ arts_fatal("Aborting. $HOME not set!");
+ }
+ if (strlen(home_dir) > (PATH_MAX-100))
+ {
+ arts_fatal("Aborting. Home directory path too long!");
+ }
+ kde_home++;
+ strncpy(kde_tmp_dir, home_dir, PATH_MAX);
+ kde_tmp_dir[ PATH_MAX ] = '\0';
+ }
+ strncat(kde_tmp_dir, kde_home, PATH_MAX - strlen(kde_tmp_dir));
+
+ /** Strip trailing '/' **/
+ if ( kde_tmp_dir[strlen(kde_tmp_dir)-1] == '/')
+ kde_tmp_dir[strlen(kde_tmp_dir)-1] = 0;
+
+ result = stat(kde_tmp_dir, &stat_buf);
+ if (result == -1)
+ {
+ return 0;
+ }
+
+ strncat(kde_tmp_dir, kde_prefix, PATH_MAX - strlen(kde_tmp_dir));
+ if (gethostname(kde_tmp_dir+strlen(kde_tmp_dir), PATH_MAX - strlen(kde_tmp_dir) - 1) != 0)
+ {
+ arts_fatal("Aborting. Could not determine hostname or hostname too long.");
+ }
+ kde_tmp_dir[sizeof(kde_tmp_dir)-1] = '\0';
+
+ result = lstat(kde_tmp_dir, &stat_buf);
+ if ((result == 0) && (S_ISDIR(stat_buf.st_mode)))
+ {
+ /* $KDEHOME/socket-$HOSTNAME is a normal directory. Do nothing. */
+ tmp_buf = (char *) malloc(PATH_MAX+1);
+ if (!tmp_buf)
+ return 0;
+
+ strncpy(tmp_buf, kde_tmp_dir, PATH_MAX);
+ tmp_buf[ PATH_MAX ] = '\0';
+
+ return tmp_buf;
+ }
+
+ if ((result == -1) && (errno == ENOENT))
+ {
+ // Link mising...
+ return 0;
+ }
+ if ((result == -1) || (!S_ISLNK(stat_buf.st_mode)))
+ {
+ arts_warning("Error: \"%s\" is not a link or a directory.\n", kde_tmp_dir);
+ return 0;
+ }
+ tmp_buf = (char *) malloc(PATH_MAX+1);
+ if (!tmp_buf)
+ return 0;
+
+ /* kde_tmp_dir is a link. Check whether it points to a valid directory. */
+ result = readlink(kde_tmp_dir, tmp_buf, PATH_MAX);
+ if (result == -1)
+ {
+ arts_warning("Error: \"%s\" could not be read.\n", kde_tmp_dir);
+ free(tmp_buf);
+ return 0;
+ }
+ tmp_buf[result] = '\0';
+// printf("Link points to \"%s\"\n", tmp_buf);
+ if (strncmp(tmp_buf, user_tmp_dir, strlen(user_tmp_dir)) != 0)
+ {
+ arts_warning("Error: \"%s\" points to \"%s\" instead of \"%s\".\n", kde_tmp_dir, tmp_buf, user_tmp_dir);
+ free(tmp_buf);
+ return 0;
+ }
+ result = check_tmp_dir(tmp_buf);
+ if (result == 0) return tmp_buf; /* Success */
+
+ free(tmp_buf);
+ return 0;
+}
+
+/* blatant and literal copy from lnusertemp to avoid kdelibs dependency */
+/* Copyright (c) 2000 Waldo Bastian <bastian@kde.org>, released under LGPL */
+
+static
+int create_link(const char *file, const char *tmp_dir)
+{
+ int result;
+ result = check_tmp_dir(tmp_dir);
+ if (result)
+ {
+ return result;
+ }
+ result = symlink(tmp_dir, file);
+ if (result == -1)
+ {
+ fprintf(stderr, "Error: Can not create link from \"%s\" to \"%s\"\n", file, tmp_dir);
+ return 1;
+ }
+ printf("Created link from \"%s\" to \"%s\"\n", file, tmp_dir);
+ return 0;
+}
+
+
+static
+int build_link(const char *tmp_prefix, const char *kde_prefix)
+{
+ struct passwd *pw_ent;
+ char kde_tmp_dir[PATH_MAX+1];
+ char user_tmp_dir[PATH_MAX+1];
+ char tmp_buf[PATH_MAX+1];
+ int uid = getuid();
+ const char *home_dir = getenv("HOME");
+ const char *kde_home = uid ? getenv("KDEHOME") : getenv("KDEROOTHOME");
+ int result;
+ struct stat stat_buf;
+
+ kde_tmp_dir[0] = 0;
+
+ pw_ent = getpwuid(uid);
+ if (!pw_ent)
+ {
+ fprintf(stderr, "Error: Can not find password entry for uid %d.\n", getuid());
+ return 1;
+ }
+
+ strncpy(user_tmp_dir, tmp_prefix, PATH_MAX);
+ user_tmp_dir[ PATH_MAX ] = '\0';
+ strncat(user_tmp_dir, pw_ent->pw_name, PATH_MAX - strlen(tmp_prefix));
+
+ if (!kde_home || !kde_home[0])
+ {
+ kde_home = "~/.kde/";
+ }
+
+ if (kde_home[0] == '~')
+ {
+ if (uid == 0)
+ {
+ home_dir = pw_ent->pw_dir ? pw_ent->pw_dir : "/root";
+ }
+ if (!home_dir || !home_dir[0])
+ {
+ fprintf(stderr, "Aborting. $HOME not set!");
+ exit(255);
+ }
+ if (strlen(home_dir) > (PATH_MAX-100))
+ {
+ fprintf(stderr, "Aborting. Home directory path too long!");
+ exit(255);
+ }
+ kde_home++;
+ strncpy(kde_tmp_dir, home_dir, PATH_MAX);
+ kde_tmp_dir[ PATH_MAX ] = '\0';
+ }
+ strncat(kde_tmp_dir, kde_home, PATH_MAX - strlen(kde_tmp_dir));
+
+ /** Strip trailing '/' **/
+ if ( kde_tmp_dir[strlen(kde_tmp_dir)-1] == '/')
+ kde_tmp_dir[strlen(kde_tmp_dir)-1] = 0;
+
+ result = stat(kde_tmp_dir, &stat_buf);
+ if ((result == -1) && (errno == ENOENT))
+ {
+ result = mkdir(kde_tmp_dir, 0700);
+ }
+ if (result == -1)
+ {
+ return 1;
+ }
+
+ strncat(kde_tmp_dir, kde_prefix, PATH_MAX - strlen(kde_tmp_dir));
+ if (gethostname(kde_tmp_dir+strlen(kde_tmp_dir), PATH_MAX - strlen(kde_tmp_dir) - 1) != 0)
+ {
+ perror("Aborting. Could not determine hostname: ");
+ exit(255);
+ }
+ kde_tmp_dir[sizeof(kde_tmp_dir)-1] = '\0';
+
+ result = lstat(kde_tmp_dir, &stat_buf);
+ if ((result == 0) && (S_ISDIR(stat_buf.st_mode)))
+ {
+ /* $KDEHOME/tmp is a normal directory. Do nothing. */
+ printf("Directory \"%s\" already exists.\n", kde_tmp_dir);
+ return 0;
+ }
+ if ((result == -1) && (errno == ENOENT))
+ {
+ printf("Creating link %s.\n", kde_tmp_dir);
+ result = create_link(kde_tmp_dir, user_tmp_dir);
+ if (result == 0) return 0; /* Success */
+ unlink(kde_tmp_dir);
+ strncat(user_tmp_dir, "XXXXXX", PATH_MAX - strlen(user_tmp_dir));
+ mktemp(user_tmp_dir); /* We want a directory, not a file, so using mkstemp makes no sense and is wrong */
+ return create_link(kde_tmp_dir, user_tmp_dir);
+ }
+ if ((result == -1) || (!S_ISLNK(stat_buf.st_mode)))
+ {
+ fprintf(stderr, "Error: \"%s\" is not a link or a directory.\n", kde_tmp_dir);
+ return 1;
+ }
+ /* kde_tmp_dir is a link. Check whether it points to a valid directory. */
+ result = readlink(kde_tmp_dir, tmp_buf, PATH_MAX);
+ if (result == -1)
+ {
+ fprintf(stderr, "Error: \"%s\" could not be read.\n", kde_tmp_dir);
+ return 1;
+ }
+ tmp_buf[result] = '\0';
+ printf("Link points to \"%s\"\n", tmp_buf);
+ if (strncmp(tmp_buf, user_tmp_dir, strlen(user_tmp_dir)) != 0)
+ {
+ fprintf(stderr, "Error: \"%s\" points to \"%s\" instead of \"%s\".\n", kde_tmp_dir, tmp_buf, user_tmp_dir);
+ unlink(kde_tmp_dir);
+ printf("Creating link %s.\n", kde_tmp_dir);
+ result = create_link(kde_tmp_dir, user_tmp_dir);
+ if (result == 0) return 0; /* Success */
+ unlink(kde_tmp_dir);
+ strncat(user_tmp_dir, "XXXXXX", PATH_MAX - strlen(user_tmp_dir));
+ mktemp(user_tmp_dir); /* We want a directory, not a file, so using mkstemp makes no sense and is wrong */
+ return create_link(kde_tmp_dir, user_tmp_dir);
+ return 1;
+ }
+ result = check_tmp_dir(tmp_buf);
+ if (result == 0) return 0; /* Success */
+ unlink(kde_tmp_dir);
+ strncat(user_tmp_dir, "XXXXXX", PATH_MAX - strlen(user_tmp_dir));
+ mktemp(user_tmp_dir); /* We want a directory, not a file, so using mkstemp makes no sense and is wrong */
+ return create_link(kde_tmp_dir, user_tmp_dir);
+}
+
+string MCOPUtils::createFilePath(string name)
+{
+ static char *mcop_dir = 0;
+ if (!mcop_dir)
+ {
+ mcop_dir = locate_mcop_dir();
+ }
+ if (!mcop_dir)
+ {
+
+ const char *tmp = 0;
+ tmp = getenv("KDETMP");
+ if (!tmp || !tmp[0])
+ tmp = getenv("TMPDIR");
+ if (!tmp || !tmp[0])
+ tmp = "/tmp";
+
+ char tmp_prefix[PATH_MAX+1];
+ strcpy(tmp_prefix, tmp);
+ strcat(tmp_prefix, "/ksocket-");
+
+ build_link(tmp_prefix, "/socket-");
+ mcop_dir = locate_mcop_dir();
+ }
+ if (!mcop_dir)
+ {
+ arts_fatal("can't create mcop directory");
+ }
+ string tmpdir = mcop_dir;
+ return tmpdir+"/"+name;
+}
+
+/*
+ * try to figure out full hostname - this is important as every client which
+ * tries to connect objects located here will need to be able to resolve that
+ * correctly
+ */
+string MCOPUtils::getFullHostname()
+{
+ char buffer[1024];
+ string result;
+ struct hostent *hp;
+
+ if(gethostname(buffer,1024) == 0) {
+ buffer[1023] = '\0';
+ result = buffer;
+ } else
+ return "localhost";
+
+ /*
+ * if gethostname() isn't a FQDN (guess that by checking whether it
+ * contains a dot), try to look it up to ensure it is
+ */
+ if(result.find('.') == string::npos && (hp = gethostbyname(buffer)) != 0)
+ result = hp->h_name;
+
+ return result;
+}
+
+string MCOPUtils::readConfigEntry(const string& key, const string& defaultValue)
+{
+ const char *home = getenv("HOME");
+ if(home)
+ {
+ string rcname = home + string("/.mcoprc");
+
+ MCOPConfig config(rcname);
+ return config.readEntry(key,defaultValue);
+ }
+ return defaultValue;
+}
+
+/** IID generation **/
+
+unsigned long MCOPUtils::makeIID(const string& interfaceName)
+{
+ static map<string, unsigned long> *iidmapobj = 0;
+ static unsigned long nextiid = 1;
+
+ if(!iidmapobj) iidmapobj = new map<string,unsigned long>;
+
+ map<string,unsigned long>& iidmap = *iidmapobj;
+
+ if(iidmap.find(interfaceName) == iidmap.end()) {
+ iidmap[interfaceName] = nextiid++;
+ return nextiid-1; // no need to lookup in the map thrice
+ }
+
+ return iidmap[interfaceName];
+}
+
+static vector<string> *readPath(const string& name, const string& defaultValue)
+{
+ vector<string> *result = 0;
+ const char *home = getenv("HOME");
+
+ if(home)
+ {
+ string rcname = home + string("/.mcoprc");
+
+ MCOPConfig config(rcname);
+ result = config.readListEntry(name);
+ }
+ if(!result)
+ result = new vector<string>;
+ if(result->empty())
+ result->push_back(defaultValue);
+
+ return result;
+}
+
+const vector<string> *MCOPUtils::extensionPath()
+{
+ static vector<string> *result = 0;
+
+ if(!result) result = readPath("ExtensionPath", EXTENSION_DIR);
+ return result;
+}
+
+const vector<string> *MCOPUtils::traderPath()
+{
+ static vector<string> *result = 0;
+
+ if(!result)
+ {
+ result = readPath("TraderPath", TRADER_DIR);
+
+ const char *home = getenv("HOME");
+ if(home) result->push_back(home + string("/.mcop/trader-cache"));
+ }
+ return result;
+}
+
+string MCOPUtils::mcopDirectory()
+{
+ static bool initialized = false;
+ static string mcopDirectory;
+
+ if(initialized)
+ return mcopDirectory;
+ initialized = true;
+
+ const char *home = getenv("HOME");
+ arts_return_val_if_fail(home != 0, "");
+
+ mcopDirectory = home + string("/.mcop");
+
+ mkdir(home,0755);
+ if(mkdir(mcopDirectory.c_str(),0755) != 0)
+ {
+ string why = strerror(errno);
+
+ struct stat st;
+ stat(mcopDirectory.c_str(),&st);
+ if(!S_ISDIR(st.st_mode))
+ {
+ arts_warning("can't create directory %s (%s)",
+ mcopDirectory.c_str(), why.c_str());
+
+ mcopDirectory = "";
+ }
+ }
+ return mcopDirectory;
+}
+
+bool MCOPUtils::tokenize(const string& line, string& key,vector<string>& values)
+{
+ string value;
+ enum { sKey, sValue, sValueQuoted, sValueQuotedEscaped, sBad } state;
+
+ state = sKey;
+ for(string::const_iterator i = line.begin(); i != line.end(); i++)
+ {
+ char c = *i;
+ unsigned char uc = static_cast<unsigned char>(c);
+
+ arts_assert(c != '\n');
+
+ if(state == sKey)
+ {
+ if(c == ' ' || c == '\t')
+ ; // ignore
+ else if(isalnum(c))
+ key += c;
+ else if(c == '=')
+ state = sValue;
+ else
+ state = sBad;
+ }
+ else if(state == sValue)
+ {
+ if(c == ' ' || c == '\t')
+ ; // ignore
+ else if(c == '"')
+ state = sValueQuoted;
+ else if(c == ',')
+ {
+ values.push_back(value);
+ value = "";
+ }
+ else if(uc > 32 && uc < 128)
+ value += c;
+ else
+ state = sBad;
+ }
+ else if(state == sValueQuoted)
+ {
+ if(c == '"')
+ state = sValue;
+ else if(c == '\\')
+ state = sValueQuotedEscaped;
+ else
+ value += c;
+ }
+ else if(state == sValueQuotedEscaped)
+ {
+ value += c;
+ state = sValueQuoted;
+ }
+ }
+ if(state == sValue)
+ values.push_back(value);
+
+ return(state != sBad);
+}