diff options
Diffstat (limited to 'kinit/lnusertemp.c')
-rw-r--r-- | kinit/lnusertemp.c | 274 |
1 files changed, 274 insertions, 0 deletions
diff --git a/kinit/lnusertemp.c b/kinit/lnusertemp.c new file mode 100644 index 000000000..70457f74f --- /dev/null +++ b/kinit/lnusertemp.c @@ -0,0 +1,274 @@ +/* + This file is part of the KDE libraries + Copyright (c) 2000 Waldo Bastian <bastian@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/un.h> + +#include <errno.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <pwd.h> +#ifdef HAVE_LIMITS_H +#include <limits.h> +#endif + +int check_tmp_dir(const char *tmp_dir); +int create_link(const char *file, const char *tmp_dir); +int build_link(const char *tmp_prefix, const char *kde_prefix); + +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)) + { + result = mkdir(tmp_dir, 0700); + if (result == -1) + { + fprintf(stderr, "Error: Can not create directory \"%s\".\n", tmp_dir); + return 1; + } + result = stat(tmp_dir, &stat_buf); + } + if ((result == -1) || (!S_ISDIR(stat_buf.st_mode))) + { + fprintf(stderr, "Error: \"%s\" is not a directory.\n", tmp_dir); + return 1; + } + + if (stat_buf.st_uid != getuid()) + { + fprintf(stderr, "Error: \"%s\" is owned by uid %d instead of uid %d.\n", tmp_dir, stat_buf.st_uid, getuid()); + return 1; + } + return 0; +} + +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; +} + + +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!\n"); + return 1; + } + if (strlen(home_dir) > (PATH_MAX-100)) + { + fprintf(stderr, "Aborting. Home directory path too long!\n"); + return 1; + } + 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) + { + perror("mkdir failed: "); + 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); + } + 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); +} + +int main(int argc, char **argv) +{ + const char *tmp = 0; + char *tmp_prefix = 0; + const char *kde_prefix = 0; + int res = 0; + + if ((argc != 2) || + ((strcmp(argv[1], "tmp")!=0) && + (strcmp(argv[1], "socket")!=0) && + (strcmp(argv[1], "cache")!=0))) + { + fprintf(stderr, "Usage: lnusertemp tmp|socket|cache\n"); + return 1; + } + + tmp = getenv("KDETMP"); + if (!tmp || !tmp[0]) + tmp = getenv("TMPDIR"); + if (!tmp || !tmp[0]) + tmp = "/tmp"; + + if (strcmp(argv[1], "tmp") == 0) + { + tmp_prefix = (char *)malloc(strlen(tmp)+strlen("/kde-")+1); + strcpy(tmp_prefix, tmp); + strcat(tmp_prefix, "/kde-"); + + kde_prefix = "/tmp-"; + } + else if (strcmp(argv[1], "socket") == 0) + { + tmp_prefix = (char *)malloc(strlen(tmp)+strlen("/ksocket-")+1); + strcpy(tmp_prefix, tmp ); + strcat(tmp_prefix, "/ksocket-" ); + + kde_prefix = "/socket-"; + } + else if (strcmp(argv[1], "cache") == 0) + { + tmp = getenv("KDEVARTMP"); + if (!tmp || !tmp[0]) + tmp = "/var/tmp"; + + tmp_prefix = (char *)malloc(strlen(tmp)+strlen("/kdecache-")+1); + strcpy(tmp_prefix, tmp ); + strcat(tmp_prefix, "/kdecache-" ); + + kde_prefix = "/cache-"; + } + + res = build_link(tmp_prefix, kde_prefix); + + free(tmp_prefix); + + return res; +} |