+#define _GNU_SOURCE
+#define __USE_GNU
+
#include <stdlib.h>
+#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/ioctl.h>
#include <pwd.h>
#include <unistd.h>
#include <dirent.h>
#include <grp.h>
#include <security/pam_appl.h>
#include <fcntl.h>
-#define __USE_GNU
#include <dlfcn.h>
+#include <utmpx.h>
#ifdef __linux__
#include <linux/vt.h>
#endif
#include <xcb/xcb.h>
#include <gio/gunixsocketaddress.h>
+#include "status.h"
+
#define LOGIN_PROMPT "login:"
static int console_fd = -1;
static int active_vt = 7;
+static gboolean status_connected = FALSE;
+
struct pam_handle
{
char *service_name;
static gchar *
redirect_path (const gchar *path)
{
- size_t offset;
- gboolean matches;
-
// Don't redirect if inside the running directory
if (g_str_has_prefix (path, g_getenv ("LIGHTDM_TEST_ROOT")))
return g_strdup (path);
if (g_str_has_prefix (path, LOCALSTATEDIR))
return g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "var", path + strlen (LOCALSTATEDIR), NULL);
+ if (g_str_has_prefix (path, DATADIR))
+ return g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "usr", "share", path + strlen (DATADIR), NULL);
+
// Don't redirect if inside the build directory
if (g_str_has_prefix (path, BUILDDIR))
return g_strdup (path);
if (g_str_has_prefix (path, "/tmp"))
- return g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "tmp", path + strlen ("tmp"), NULL);
+ return g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "tmp", path + strlen ("/tmp"), NULL);
return g_strdup (path);
}
return result;
}
+int
+unlinkat (int dirfd, const char *pathname, int flags)
+{
+ int (*_unlinkat) (int dirfd, const char *pathname, int flags);
+ gchar *new_path = NULL;
+ int result;
+
+ _unlinkat = (int (*)(int dirfd, const char *pathname, int flags)) dlsym (RTLD_NEXT, "unlinkat");
+
+ new_path = redirect_path (pathname);
+ result = _unlinkat (dirfd, new_path, flags);
+ g_free (new_path);
+
+ return result;
+}
+
int
creat (const char *pathname, mode_t mode)
{
gchar *new_path = NULL;
int ret;
+ /* Look like systemd is always running */
+ if (strcmp (pathname, "/run/systemd/seats/") == 0)
+ return 1;
+
_access = (int (*)(const char *pathname, int mode)) dlsym (RTLD_NEXT, "access");
new_path = redirect_path (pathname);
}
int
-stat64 (const char *path, struct stat *buf)
+stat64 (const char *path, struct stat64 *buf)
{
- int (*_stat64) (const char *path, struct stat *buf);
+ int (*_stat64) (const char *path, struct stat64 *buf);
gchar *new_path = NULL;
int ret;
- _stat64 = (int (*)(const char *path, struct stat *buf)) dlsym (RTLD_NEXT, "stat64");
+ _stat64 = (int (*)(const char *path, struct stat64 *buf)) dlsym (RTLD_NEXT, "stat64");
new_path = redirect_path (path);
- ret = _stat (new_path, buf);
+ ret = _stat64 (new_path, buf);
g_free (new_path);
return ret;
}
int
-__xstat64 (int version, const char *path, struct stat *buf)
+__xstat64 (int version, const char *path, struct stat64 *buf)
{
- int (*___xstat64) (int version, const char *path, struct stat *buf);
+ int (*___xstat64) (int version, const char *path, struct stat64 *buf);
gchar *new_path = NULL;
int ret;
- ___xstat64 = (int (*)(int version, const char *path, struct stat *buf)) dlsym (RTLD_NEXT, "__xstat64");
+ ___xstat64 = (int (*)(int version, const char *path, struct stat64 *buf)) dlsym (RTLD_NEXT, "__xstat64");
new_path = redirect_path (path);
ret = ___xstat64 (version, new_path, buf);
return ret;
}
+int
+__fxstatat(int ver, int dirfd, const char *pathname, struct stat *buf, int flags)
+{
+ int (*___fxstatat) (int ver, int dirfd, const char *pathname, struct stat *buf, int flags);
+ gchar *new_path = NULL;
+ int ret;
+
+ ___fxstatat = (int (*)(int ver, int dirfd, const char *pathname, struct stat *buf, int flags)) dlsym (RTLD_NEXT, "__fxstatat");
+
+ new_path = redirect_path (pathname);
+ ret = ___fxstatat (ver, dirfd, new_path, buf, flags);
+ g_free (new_path);
+
+ return ret;
+}
+
+int
+__fxstatat64(int ver, int dirfd, const char *pathname, struct stat64 *buf, int flags)
+{
+ int (*___fxstatat64) (int ver, int dirfd, const char *pathname, struct stat64 *buf, int flags);
+ gchar *new_path = NULL;
+ int ret;
+
+ ___fxstatat64 = (int (*)(int ver, int dirfd, const char *pathname, struct stat64 *buf, int flags)) dlsym (RTLD_NEXT, "__fxstatat64");
+
+ new_path = redirect_path (pathname);
+ ret = ___fxstatat64 (ver, dirfd, new_path, buf, flags);
+ g_free (new_path);
+
+ return ret;
+}
+
DIR *
opendir (const char *name)
{
}
int
-ioctl (int d, int request, void *data)
+chmod (const char *path, mode_t mode)
{
- int (*_ioctl) (int d, int request, void *data);
+ int (*_chmod) (const char *path, mode_t mode);
+ gchar *new_path = NULL;
+ int result;
+
+ _chmod = (int (*)(const char *path, mode_t mode)) dlsym (RTLD_NEXT, "chmod");
+
+ new_path = redirect_path (path);
+ result = _chmod (new_path, mode);
+ g_free (new_path);
- _ioctl = (int (*)(int d, int request, void *data)) dlsym (RTLD_NEXT, "ioctl");
+ return result;
+}
+
+int
+ioctl (int d, unsigned long request, ...)
+{
+ int (*_ioctl) (int d, int request, ...);
+
+ _ioctl = (int (*)(int d, int request, ...)) dlsym (RTLD_NEXT, "ioctl");
if (d > 0 && d == console_fd)
{
struct vt_stat *console_state;
- int *n;
+ int vt;
+ va_list ap;
switch (request)
{
case VT_GETSTATE:
- console_state = data;
+ va_start (ap, request);
+ console_state = va_arg (ap, struct vt_stat *);
+ va_end (ap);
console_state->v_active = active_vt;
break;
case VT_ACTIVATE:
- active_vt = GPOINTER_TO_INT (data);
+ va_start (ap, request);
+ vt = va_arg (ap, int);
+ va_end (ap);
+ if (vt != active_vt)
+ {
+ active_vt = vt;
+ if (!status_connected)
+ status_connected = status_connect (NULL);
+ status_notify ("VT ACTIVATE VT=%d", active_vt);
+ }
break;
case VT_WAITACTIVE:
break;
return 0;
}
else
+ {
+ va_list ap;
+ void *data;
+
+ va_start (ap, request);
+ data = va_arg (ap, void *);
+ va_end (ap);
return _ioctl (d, request, data);
+ }
}
int
}
static void
-load_passwd_file ()
+load_passwd_file (void)
{
gchar *path, *data = NULL, **lines;
gint i;
}
static void
-load_group_file ()
+load_group_file (void)
{
gchar *path, *data = NULL, **lines;
gint i;
msg = malloc (sizeof (struct pam_message *) * 1);
msg[0] = malloc (sizeof (struct pam_message));
msg[0]->msg_style = PAM_PROMPT_ECHO_OFF;
- msg[0]->msg = "Enter new password:";
+ if ((flags & PAM_CHANGE_EXPIRED_AUTHTOK) != 0)
+ msg[0]->msg = "Enter new password (expired):";
+ else
+ msg[0]->msg = "Enter new password:";
result = pamh->conversation.conv (1, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
free (msg[0]);
free (msg);
if (group)
{
groups_length = getgroups (0, NULL);
+ if (groups_length < 0)
+ return PAM_SYSTEM_ERR;
groups = malloc (sizeof (gid_t) * (groups_length + 1));
groups_length = getgroups (groups_length, groups);
+ if (groups_length < 0)
+ return PAM_SYSTEM_ERR;
groups[groups_length] = group->gr_gid;
groups_length++;
setgroups (groups_length, groups);
{
}
-struct utmp *
-pututxline (struct utmp *ut)
+struct utmpx *
+pututxline (const struct utmpx *ut)
{
- return ut;
+ return (struct utmpx *)ut;
}
void
{
xcb_connection_t *c;
gchar *socket_path;
- GSocketAddress *address;
GError *error = NULL;
c = malloc (sizeof (xcb_connection_t));
if (c->error == 0)
{
gchar *d;
+ GSocketAddress *address;
/* Skip the hostname, we'll assume it's localhost */
d = g_strdup_printf (".x%s", strchr (display, ':'));
address = g_unix_socket_address_new (socket_path);
if (!g_socket_connect (c->socket, address, NULL, &error))
c->error = XCB_CONN_ERROR;
+ g_object_unref (address);
if (error)
g_printerr ("Failed to connect to X socket %s: %s\n", socket_path, error->message);
g_free (socket_path);
{
}
- g_object_unref (address);
-
return c;
}