summaryrefslogtreecommitdiff
path: root/daemon
diff options
context:
space:
mode:
authorWilliam Jon McCann <mccann@jhu.edu>2005-07-19 23:39:43 +0000
committerWilliam Jon McCann <mccann@src.gnome.org>2005-07-19 23:39:43 +0000
commitf3806b9da53dd41301c27258711dbf6d84bb913a (patch)
tree73e0297531a5de206a6a8066b5b0a47383ed51ef /daemon
parent3d38a4c9747ca77a3621fff99ed15db371968e0b (diff)
downloadgdm-f3806b9da53dd41301c27258711dbf6d84bb913a.tar.gz
Use common function for loading face images.
2005-07-19 William Jon McCann <mccann@jhu.edu> * gui/greeter/greeter_item_ulist.c (gdm_greeter_users_init): Use common function for loading face images. * gui/greeter/greeter.c (greeter_ctrl_handler): Update for new common code. * gui/gdmuser.c (gdm_user_alloc): Use common function for loading face images. (setup_user): Define as static. * gui/gdmlogin.c (gdm_kill_thingies): Make static. (gdm_login_ctrl_handler): Update for new gdm_common_login_sound. Add gdm_kill_thingies before all abort calls since they are not in gdm_common_abort anymore. (main): Use new common get face function. * gui/Makefile.am: * gui/gdmcommon.c (gdm_common_show_info_msg, gdm_common_login_sound): Make more common by not depending on external variables. (gdm_common_abort): Make more common by not depending on external functions. (gdm_common_get_face): Add a common function for loading face images. * daemon/slave.c (path_is_local, check_user_file) (check_global_file, get_facefile_from_gnome2_dir_config) (get_facefile_from_home, get_facefile_from_global, run_pictures): Don't stat or read from remote home directories. Fixes #310545. * configure.in: * daemon/Makefile.am: * daemon/fstype.c: Add ability to detect filesystem types. * gui/greeter/greeter_item_ulist.c (gdm_greeter_users_init): * gui/gdmlogin.c (main): Try GTK+ themed icon stock_person before falling back to nobody.png. Fixes #310906.
Diffstat (limited to 'daemon')
-rw-r--r--daemon/Makefile.am1
-rw-r--r--daemon/fstype.c420
-rw-r--r--daemon/slave.c421
3 files changed, 665 insertions, 177 deletions
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index f304aa69..14047950 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -29,6 +29,7 @@ gdm_binary_SOURCES = \
gdm.h \
display.c \
display.h \
+ fstype.c \
slave.c \
slave.h \
server.c \
diff --git a/daemon/fstype.c b/daemon/fstype.c
new file mode 100644
index 00000000..e6bef2fc
--- /dev/null
+++ b/daemon/fstype.c
@@ -0,0 +1,420 @@
+/* fstype.c -- determine type of filesystems that files are on
+ Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc.
+
+ 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, or (at your option)
+ any later version.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* This code was relicensed by the FSF on May 1 2002
+
+ This file 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 file 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 the Gnome 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.
+ */
+/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
+
+#include <config.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#else
+extern int errno;
+#endif
+#include <string.h>
+#include <glib.h>
+#ifdef HAVE_LIBGEN_H
+#include <libgen.h>
+#endif
+
+#if __STDC__
+# define P_(s) s
+#else
+# define P_(s) ()
+#endif
+
+static char *filesystem_type_uncached P_((char *path, char *relpath, struct stat *statp));
+
+void fstype_internal_error (int level, int num, char const *fmt, ...);
+
+#ifdef FSTYPE_MNTENT /* 4.3BSD etc. */
+static int xatoi P_((char *cp));
+#endif
+
+#ifdef FSTYPE_MNTENT /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
+#include <mntent.h>
+#if !defined(MOUNTED)
+# if defined(MNT_MNTTAB) /* HP-UX. */
+# define MOUNTED MNT_MNTTAB
+# endif
+# if defined(MNTTABNAME) /* Dynix. */
+# define MOUNTED MNTTABNAME
+# endif
+#endif
+#endif
+
+#ifdef FSTYPE_GETMNT /* Ultrix. */
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/fs_types.h>
+#endif
+
+#ifdef FSTYPE_USG_STATFS /* SVR3. */
+#include <sys/statfs.h>
+#include <sys/fstyp.h>
+#endif
+
+#ifdef FSTYPE_STATVFS /* SVR4. */
+#include <sys/statvfs.h>
+#include <sys/fstyp.h>
+#endif
+
+#ifdef FSTYPE_STATFS /* 4.4BSD. */
+#include <sys/param.h> /* NetBSD needs this. */
+#include <sys/mount.h>
+
+#ifndef MFSNAMELEN /* NetBSD defines this. */
+static char *
+fstype_to_string (t)
+ short t;
+{
+#ifdef INITMOUNTNAMES /* Defined in 4.4BSD, not in NET/2. */
+ static char *mn[] = INITMOUNTNAMES;
+ if (t >= 0 && t <= MOUNT_MAXTYPE)
+ return mn[t];
+ else
+ return "?";
+#else /* !INITMOUNTNAMES */
+ switch (t)
+ {
+ case MOUNT_UFS:
+ return "ufs";
+ case MOUNT_NFS:
+ return "nfs";
+#ifdef MOUNT_PC
+ case MOUNT_PC:
+ return "pc";
+#endif
+#ifdef MOUNT_MFS
+ case MOUNT_MFS:
+ return "mfs";
+#endif
+#ifdef MOUNT_LO
+ case MOUNT_LO:
+ return "lofs";
+#endif
+#ifdef MOUNT_TFS
+ case MOUNT_TFS:
+ return "tfs";
+#endif
+#ifdef MOUNT_TMP
+ case MOUNT_TMP:
+ return "tmp";
+#endif
+#ifdef MOUNT_MSDOS
+ case MOUNT_MSDOS:
+ return "msdos";
+#endif
+#ifdef MOUNT_ISO9660
+ case MOUNT_ISO9660:
+ return "iso9660fs";
+#endif
+ default:
+ return "?";
+ }
+#endif /* !INITMOUNTNAMES */
+}
+#endif /* !MFSNAMELEN */
+#endif /* FSTYPE_STATFS */
+
+#ifdef FSTYPE_AIX_STATFS /* AIX. */
+#include <sys/vmount.h>
+#include <sys/statfs.h>
+
+#define FSTYPE_STATFS /* Otherwise like 4.4BSD. */
+#define f_type f_vfstype
+
+static char *
+fstype_to_string (t)
+ short t;
+{
+ switch (t)
+ {
+ case MNT_AIX:
+#if 0 /* NFS filesystems are actually MNT_AIX. */
+ return "aix";
+#endif
+ case MNT_NFS:
+ return "nfs";
+ case MNT_JFS:
+ return "jfs";
+ case MNT_CDROM:
+ return "cdrom";
+ default:
+ return "?";
+ }
+}
+#endif /* FSTYPE_AIX_STATFS */
+
+#ifdef AFS
+#include <netinet/in.h>
+#include <afs/venus.h>
+#if __STDC__
+/* On SunOS 4, afs/vice.h defines this to rely on a pre-ANSI cpp. */
+#undef _VICEIOCTL
+#define _VICEIOCTL(id) ((unsigned int ) _IOW('V', id, struct ViceIoctl))
+#endif
+#ifndef _IOW
+/* AFS on Solaris 2.3 doesn't get this definition. */
+#include <sys/ioccom.h>
+#endif
+
+static int
+in_afs (path)
+ char *path;
+{
+ static char space[2048];
+ struct ViceIoctl vi;
+
+ vi.in_size = 0;
+ vi.out_size = sizeof (space);
+ vi.out = space;
+
+ if (pioctl (path, VIOC_FILE_CELL_NAME, &vi, 1)
+ && (errno == EINVAL || errno == ENOENT))
+ return 0;
+ return 1;
+}
+#endif /* AFS */
+
+/* Nonzero if the current filesystem's type is known. */
+static int fstype_known = 0;
+
+char *filesystem_type (char *path, char *relpath, struct stat *statp);
+/* Return a static string naming the type of filesystem that the file PATH,
+ described by STATP, is on.
+ RELPATH is the file name relative to the current directory.
+ Return "unknown" if its filesystem type is unknown. */
+
+char *
+filesystem_type (char *path, char *relpath, struct stat *statp)
+{
+ static char *current_fstype = NULL;
+ static dev_t current_dev;
+
+ if (current_fstype != NULL)
+ {
+ if (fstype_known && statp->st_dev == current_dev)
+ return current_fstype; /* Cached value. */
+ g_free (current_fstype);
+ }
+ current_dev = statp->st_dev;
+ current_fstype = filesystem_type_uncached (path, relpath, statp);
+ return current_fstype;
+}
+
+void
+fstype_internal_error (int level, int num, char const *fmt, ...)
+{
+}
+
+/* Return a newly allocated string naming the type of filesystem that the
+ file PATH, described by STATP, is on.
+ RELPATH is the file name relative to the current directory.
+ Return "unknown" if its filesystem type is unknown. */
+
+static char *
+filesystem_type_uncached (char *path, char *relpath, struct stat *statp)
+{
+ char *type = NULL;
+
+#ifdef FSTYPE_MNTENT /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
+ char *table = MOUNTED;
+ FILE *mfp;
+ struct mntent *mnt;
+
+ mfp = setmntent (table, "r");
+ if (mfp == NULL) {
+ fstype_internal_error (1, errno, "%s", table);
+ goto no_mtab;
+ }
+
+ /* Find the entry with the same device number as STATP, and return
+ that entry's fstype. */
+ while (type == NULL && (mnt = getmntent (mfp)))
+ {
+ char *devopt;
+ dev_t dev;
+ struct stat disk_stats;
+
+#ifdef MNTTYPE_IGNORE
+ if (!strcmp (mnt->mnt_type, MNTTYPE_IGNORE))
+ continue;
+#endif
+
+ /* Newer systems like SunOS 4.1 keep the dev number in the mtab,
+ in the options string. For older systems, we need to stat the
+ directory that the filesystem is mounted on to get it.
+
+ Unfortunately, the HPUX 9.x mnttab entries created by automountq
+ contain a dev= option but the option value does not match the
+ st_dev value of the file (maybe the lower 16 bits match?). */
+
+#if !defined(hpux) && !defined(__hpux__)
+ devopt = strstr (mnt->mnt_opts, "dev=");
+ if (devopt)
+ {
+ if (devopt[4] == '0' && (devopt[5] == 'x' || devopt[5] == 'X'))
+ dev = xatoi (devopt + 6);
+ else
+ dev = xatoi (devopt + 4);
+ }
+ else
+#endif /* not hpux */
+ {
+ if (stat (mnt->mnt_dir, &disk_stats) == -1) {
+ if (errno == EACCES)
+ continue;
+ else
+ fstype_internal_error (1, errno, "error in %s: %s", table, mnt->mnt_dir);
+ }
+ dev = disk_stats.st_dev;
+ }
+
+ if (dev == statp->st_dev)
+ type = mnt->mnt_type;
+ }
+
+ if (endmntent (mfp) == 0)
+ fstype_internal_error (0, errno, "%s", table);
+ no_mtab:
+#endif
+
+#ifdef FSTYPE_GETMNT /* Ultrix. */
+ int offset = 0;
+ struct fs_data fsd;
+
+ while (type == NULL
+ && getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY, 0) > 0)
+ {
+ if (fsd.fd_req.dev == statp->st_dev)
+ type = gt_names[fsd.fd_req.fstype];
+ }
+#endif
+
+#ifdef FSTYPE_USG_STATFS /* SVR3. */
+ struct statfs fss;
+ char typebuf[FSTYPSZ];
+
+ if (statfs (relpath, &fss, sizeof (struct statfs), 0) == -1)
+ {
+ /* Don't die if a file was just removed. */
+ if (errno != ENOENT)
+ fstype_internal_error (1, errno, "%s", path);
+ }
+ else if (!sysfs (GETFSTYP, fss.f_fstyp, typebuf))
+ type = typebuf;
+#endif
+
+#ifdef FSTYPE_STATVFS /* SVR4. */
+ struct statvfs fss;
+
+ if (statvfs (relpath, &fss) == -1)
+ {
+ /* Don't die if a file was just removed. */
+ if (errno != ENOENT)
+ fstype_internal_error (1, errno, "%s", path);
+ }
+ else
+ type = fss.f_basetype;
+#endif
+
+#ifdef FSTYPE_STATFS /* 4.4BSD. */
+ struct statfs fss;
+ char *p;
+
+ if (S_ISLNK (statp->st_mode))
+ p = dirname (relpath);
+ else
+ p = relpath;
+
+ if (statfs (p, &fss) == -1)
+ {
+ /* Don't die if symlink to nonexisting file, or a file that was
+ just removed. */
+ if (errno != ENOENT)
+ fstype_internal_error (1, errno, "%s", path);
+ }
+ else
+ {
+#ifdef MFSNAMELEN /* NetBSD. */
+ type = fss.f_fstypename;
+#else
+ type = fstype_to_string (fss.f_type);
+#endif
+ }
+ if (p != relpath)
+ free (p);
+#endif
+
+#ifdef AFS
+ if ((!type || !strcmp (type, "xx")) && in_afs (relpath))
+ type = "afs";
+#endif
+
+ /* An unknown value can be caused by an ENOENT error condition.
+ Don't cache those values. */
+ fstype_known = (type != NULL);
+
+ return g_strdup (type ? type : "unknown");
+}
+
+#ifdef FSTYPE_MNTENT /* 4.3BSD etc. */
+/* Return the value of the hexadecimal number represented by CP.
+ No prefix (like '0x') or suffix (like 'h') is expected to be
+ part of CP. */
+
+static int
+xatoi (char *cp)
+{
+ int val;
+
+ val = 0;
+ while (*cp)
+ {
+ if (*cp >= 'a' && *cp <= 'f')
+ val = val * 16 + *cp - 'a' + 10;
+ else if (*cp >= 'A' && *cp <= 'F')
+ val = val * 16 + *cp - 'A' + 10;
+ else if (*cp >= '0' && *cp <= '9')
+ val = val * 16 + *cp - '0';
+ else
+ break;
+ cp++;
+ }
+ return val;
+}
+#endif
diff --git a/daemon/slave.c b/daemon/slave.c
index 9cf63b23..f3d450b5 100644
--- a/daemon/slave.c
+++ b/daemon/slave.c
@@ -1,4 +1,6 @@
-/* GDM - The GNOME Display Manager
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * GDM - The GNOME Display Manager
* Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net>
*
* This program is free software; you can redistribute it and/or modify
@@ -2097,6 +2099,240 @@ is_in_trusted_pic_dir (const char *path)
return FALSE;
}
+static GHashTable *fstype_hash = NULL;
+extern char *filesystem_type (char *path, char *relpath, struct stat *statp);
+
+static gboolean
+path_is_local (const char *path)
+{
+ gpointer local = NULL;
+
+ if (path == NULL)
+ return FALSE;
+
+ if (fstype_hash == NULL)
+ fstype_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+ else
+ local = g_hash_table_lookup (fstype_hash, path);
+
+ if (local == NULL) {
+ struct stat statbuf;
+
+ if (stat (path, &statbuf) == 0) {
+ char *type = filesystem_type ((char *)path, (char *)path, &statbuf);
+ gboolean is_local = ((strcmp (type, "nfs") != 0) &&
+ (strcmp (type, "afs") != 0) &&
+ (strcmp (type, "autofs") != 0) &&
+ (strcmp (type, "unknown") != 0) &&
+ (strcmp (type, "ncpfs") != 0));
+ local = GINT_TO_POINTER (is_local ? 1 : -1);
+ g_hash_table_insert (fstype_hash, g_strdup (path), local);
+ }
+ }
+
+ return GPOINTER_TO_INT (local) > 0;
+}
+
+static gboolean
+check_user_file (const char *path,
+ guint uid)
+{
+ char *dir;
+ char *file;
+ gboolean is_ok;
+
+ if (path == NULL)
+ return FALSE;
+
+ if (access (path, R_OK) != 0)
+ return FALSE;
+
+ dir = g_path_get_dirname (path);
+ file = g_path_get_basename (path);
+
+ is_ok = gdm_file_check ("run_pictures",
+ uid,
+ dir,
+ file,
+ TRUE, TRUE,
+ GdmUserMaxFile,
+ GdmRelaxPerms);
+ g_free (dir);
+ g_free (file);
+
+ return is_ok;
+}
+
+static gboolean
+check_global_file (const char *path,
+ guint uid)
+{
+ if (path == NULL)
+ return FALSE;
+
+ if (access (path, R_OK) != 0)
+ return FALSE;
+
+ return TRUE;
+}
+
+static char *
+get_facefile_from_gnome2_dir_config (const char *homedir,
+ guint uid)
+{
+ char *picfile = NULL;
+ char *cfgdir;
+
+ /* Sanity check on ~user/.gnome2/gdm */
+ cfgdir = g_build_filename (homedir, ".gnome2", "gdm", NULL);
+ if (G_LIKELY (check_user_file (cfgdir, uid))) {
+ VeConfig *cfg;
+ char *cfgfile;
+
+ cfgfile = g_build_filename (homedir, ".gnome2", "gdm", NULL);
+ cfg = ve_config_new (cfgfile);
+ g_free (cfgfile);
+
+ picfile = ve_config_get_string (cfg, "face/picture=");
+ ve_config_destroy (cfg);
+
+ /* must exist and be absolute (note that this check
+ * catches empty strings)*/
+ /* Note that these days we just set ~/.face */
+ if G_UNLIKELY (picfile != NULL &&
+ (picfile[0] != '/' ||
+ /* this catches readability by user */
+ access (picfile, R_OK) != 0)) {
+ g_free (picfile);
+ picfile = NULL;
+ }
+
+ if (picfile != NULL) {
+ char buf[PATH_MAX];
+ if (realpath (picfile, buf) == NULL) {
+ g_free (picfile);
+ picfile = NULL;
+ } else {
+ g_free (picfile);
+ picfile = g_strdup (buf);
+ }
+ }
+
+ if G_UNLIKELY (picfile != NULL) {
+ if (! is_in_trusted_pic_dir (picfile)) {
+ /* if not in trusted dir, check it out */
+
+ /* Note that strict permissions checking is done
+ * on this file. Even if it may not even be owned by the
+ * user. This setting should ONLY point to pics in trusted
+ * dirs. */
+ if (! check_user_file (picfile, uid)) {
+ g_free (picfile);
+ picfile = NULL;
+ }
+ }
+ }
+ }
+ g_free (cfgdir);
+
+ return picfile;
+}
+
+static char *
+get_facefile_from_home (const char *homedir,
+ guint uid)
+{
+ char *picfile = NULL;
+ char *path;
+ gboolean is_local;
+
+ /* special case: look at parent of home to detect autofs
+ this is so we don't try to trigger an automount */
+ path = g_path_get_dirname (homedir);
+ is_local = path_is_local (path);
+ g_free (path);
+
+ /* now check that home dir itself is local */
+ if (is_local) {
+ is_local = path_is_local (homedir);
+ }
+
+ /* only look at local home directories so we don't try to
+ read from remote (e.g. NFS) volumes */
+ if (! is_local)
+ return NULL;
+
+
+ picfile = g_build_filename (homedir, ".face", NULL);
+
+ if (check_user_file (picfile, uid))
+ return picfile;
+ else {
+ g_free (picfile);
+ picfile = NULL;
+ }
+
+ picfile = g_build_filename (homedir, ".face.icon", NULL);
+
+ if (check_user_file (picfile, uid))
+ return picfile;
+ else {
+ g_free (picfile);
+ picfile = NULL;
+ }
+
+ picfile = get_facefile_from_gnome2_dir_config (homedir, uid);
+ if (check_user_file (picfile, uid))
+ return picfile;
+ else {
+ g_free (picfile);
+ picfile = NULL;
+ }
+
+ /* Nothing found yet, try the old locations */
+
+ picfile = g_build_filename (homedir, ".gnome2", "photo", NULL);
+ if (check_user_file (picfile, uid))
+ return picfile;
+ else {
+ g_free (picfile);
+ picfile = NULL;
+ }
+
+ picfile = g_build_filename (homedir, ".gnome", "photo", NULL);
+ if (check_user_file (picfile, uid))
+ return picfile;
+ else {
+ g_free (picfile);
+ picfile = NULL;
+ }
+
+ return NULL;
+}
+
+static gchar *
+get_facefile_from_global (const char *username,
+ guint uid)
+{
+ char *picfile = NULL;
+
+ /* Try the global face directory */
+
+ picfile = g_build_filename (GdmGlobalFaceDir,
+ username, NULL);
+
+ if (check_global_file (picfile, uid))
+ return picfile;
+
+ picfile = gdm_make_filename (GdmGlobalFaceDir,
+ username, ".png");
+
+ if (check_global_file (picfile, uid))
+ return picfile;
+
+ return NULL;
+}
+
/* This is VERY evil! */
static void
run_pictures (void)
@@ -2107,9 +2343,7 @@ run_pictures (void)
size_t bytes;
struct passwd *pwent;
char *picfile;
- char *picdir;
FILE *fp;
- char *cfgdir;
response = NULL;
for (;;) {
@@ -2140,182 +2374,15 @@ run_pictures (void)
continue;
}
- if G_LIKELY (picfile == NULL) {
- picfile = g_build_filename (pwent->pw_dir, ".face", NULL);
- if (access (picfile, R_OK) != 0) {
- g_free (picfile);
- picfile = NULL;
- } else if G_UNLIKELY ( ! gdm_file_check ("run_pictures", pwent->pw_uid,
- pwent->pw_dir, ".face", TRUE, TRUE, GdmUserMaxFile,
- GdmRelaxPerms)) {
- g_free (picfile);
-
- NEVER_FAILS_root_set_euid_egid (0, GdmGroupId);
-
- gdm_slave_greeter_ctl_no_ret (GDM_READPIC, "");
- continue;
- }
- }
-
- if (picfile == NULL) {
- picfile = g_build_filename (pwent->pw_dir, ".face.icon", NULL);
- if (access (picfile, R_OK) != 0) {
- g_free (picfile);
- picfile = NULL;
- } else if G_UNLIKELY ( ! gdm_file_check ("run_pictures", pwent->pw_uid,
- pwent->pw_dir, ".face.icon", TRUE, TRUE, GdmUserMaxFile,
- GdmRelaxPerms)) {
- g_free (picfile);
-
- NEVER_FAILS_root_set_euid_egid (0, GdmGroupId);
-
- gdm_slave_greeter_ctl_no_ret (GDM_READPIC, "");
- continue;
- }
- }
-
- if (picfile == NULL) {
- /* Sanity check on ~user/.gnome2/gdm */
- cfgdir = g_build_filename (pwent->pw_dir, ".gnome2", "gdm", NULL);
- if G_LIKELY (gdm_file_check ("run_pictures", pwent->pw_uid,
- cfgdir, "gdm", TRUE, TRUE, GdmUserMaxFile,
- GdmRelaxPerms)) {
- VeConfig *cfg;
- char *cfgfile;
-
- cfgfile = g_build_filename (pwent->pw_dir, ".gnome2", "gdm", NULL);
- cfg = ve_config_new (cfgfile);
- g_free (cfgfile);
- picfile = ve_config_get_string (cfg, "face/picture=");
- ve_config_destroy (cfg);
-
- /* must exist and be absolute (note that this check
- * catches empty strings)*/
- /* Note that these days we just set ~/.face */
- if G_UNLIKELY (picfile != NULL &&
- (picfile[0] != '/' ||
- /* this catches readability by user */
- access (picfile, R_OK) != 0)) {
- g_free (picfile);
- picfile = NULL;
- }
-
- if (picfile != NULL) {
- char buf[PATH_MAX];
- if (realpath (picfile, buf) == NULL) {
- g_free (picfile);
- picfile = NULL;
- } else {
- g_free (picfile);
- picfile = g_strdup (buf);
- }
- }
-
- if G_UNLIKELY (picfile != NULL) {
- char *dir;
- char *base;
-
- /* if in trusted dir, just use it */
- if (is_in_trusted_pic_dir (picfile)) {
- struct stat s;
-
- if (stat (picfile, &s) != 0 ||
- ! S_ISREG (s.st_mode)) {
- g_free (picfile);
- picfile = g_strdup ("");
- }
- NEVER_FAILS_root_set_euid_egid (0, GdmGroupId);
-
- g_free (cfgdir);
-
- gdm_slave_greeter_ctl_no_ret (GDM_READPIC,
- picfile);
- g_free (picfile);
- continue;
- }
-
- /* if not in trusted dir, check it out */
- dir = g_path_get_dirname (picfile);
- base = g_path_get_basename (picfile);
-
- /* Note that strict permissions checking is done
- * on this file. Even if it may not even be owned by the
- * user. This setting should ONLY point to pics in trusted
- * dirs. */
- if (ve_string_empty (dir) ||
- ve_string_empty (base) ||
- ! gdm_file_check ("run_pictures", pwent->pw_uid,
- dir, base, TRUE, TRUE, GdmUserMaxFile,
- GdmRelaxPerms)) {
- g_free (picfile);
- picfile = NULL;
- }
-
- g_free (base);
- g_free (dir);
- }
- }
- g_free (cfgdir);
- }
-
- /* Nothing found yet, try the old location,
- * and if we don't find anything there we try the global
- * dir. So this is NOT JUST A FALLBACK, don't remove
- * this branch in the future! */
- if (picfile == NULL) {
- picfile = g_build_filename (pwent->pw_dir, ".gnome2", "photo", NULL);
- picdir = g_build_filename (pwent->pw_dir, ".gnome2", NULL);
- if (access (picfile, F_OK) != 0) {
- g_free (picfile);
- picfile = g_build_filename (pwent->pw_dir, ".gnome", "photo", NULL);
- g_free (picdir);
- picdir = g_build_filename (pwent->pw_dir, ".gnome", NULL);
- }
- if (access (picfile, F_OK) != 0) {
- NEVER_FAILS_root_set_euid_egid (0, GdmGroupId);
+ picfile = get_facefile_from_home (pwent->pw_dir, pwent->pw_uid);
- /* Try the global face directory */
+ if (! picfile)
+ picfile = get_facefile_from_global (pwent->pw_name, pwent->pw_uid);
- g_free (picfile);
- g_free (picdir);
- picfile = g_build_filename (GdmGlobalFaceDir,
- response, NULL);
-
- if (access (picfile, R_OK) == 0) {
- gdm_slave_greeter_ctl_no_ret (GDM_READPIC,
- picfile);
- g_free (picfile);
- continue;
- }
-
- g_free (picfile);
- picfile = gdm_make_filename (GdmGlobalFaceDir,
- response, ".png");
-
- if (access (picfile, R_OK) == 0) {
- gdm_slave_greeter_ctl_no_ret (GDM_READPIC,
- picfile);
- g_free (picfile);
- continue;
- }
-
- gdm_slave_greeter_ctl_no_ret (GDM_READPIC, "");
- g_free (picfile);
- continue;
- }
-
- /* Sanity check on ~user/.gnome[2]/photo */
- if ( ! gdm_file_check ("run_pictures", pwent->pw_uid,
- picdir, "photo", TRUE, TRUE, GdmUserMaxFile,
- GdmRelaxPerms)) {
- g_free (picdir);
-
- NEVER_FAILS_root_set_euid_egid (0, GdmGroupId);
-
- gdm_slave_greeter_ctl_no_ret (GDM_READPIC, "");
- continue;
- }
- g_free (picdir);
+ if (! picfile) {
+ NEVER_FAILS_root_set_euid_egid (0, GdmGroupId);
+ gdm_slave_greeter_ctl_no_ret (GDM_READPIC, "");
+ continue;
}
VE_IGNORE_EINTR (r = stat (picfile, &s));