2005-11-25 Brian Cameron <Brian.Cameron@sun.com> * configure.in, capplets/about-me/Makefile.am capplets/about-me/gnome-about-me.c, capplets/about-me/gnome-about-me-password.c: Fix so that gnome-about-me works on non-linux systems which do not have forkpty().
786 lines
19 KiB
C
786 lines
19 KiB
C
/* gnome-about-me.c
|
|
* Copyright (C) 2002 Diego Gonzalez
|
|
*
|
|
* Written by: Diego Gonzalez <diego@pemas.net>
|
|
*
|
|
* 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., 59 Temple Place - Suite 330, Boston, MA
|
|
* 02111-1307, USA.
|
|
*
|
|
* Parts of this code come from Gnome-System-Tools.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include <config.h>
|
|
#endif
|
|
|
|
#include <stropts.h>
|
|
#include <gnome.h>
|
|
#include <pwd.h>
|
|
#include <stdlib.h>
|
|
#include <glade/glade.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/wait.h>
|
|
#include <sys/poll.h>
|
|
#include <termios.h>
|
|
#if HAVE_PTY_H
|
|
#include <pty.h>
|
|
#endif
|
|
#if HAVE_STROPTS_H
|
|
#include <stropts.h>
|
|
#endif
|
|
|
|
#if __sun
|
|
#include <sys/types.h>
|
|
#include <signal.h>
|
|
#endif
|
|
|
|
#include "capplet-util.h"
|
|
#include "eel-alert-dialog.h"
|
|
|
|
#ifndef HAVE_FORKPTY
|
|
pid_t forkpty(int *, char *, struct termios *, struct winsize *);
|
|
#endif
|
|
|
|
typedef struct {
|
|
GladeXML *xml;
|
|
|
|
GtkWidget *old_password;
|
|
GtkWidget *new_password;
|
|
GtkWidget *retyped_password;
|
|
|
|
guint timeout_id;
|
|
guint check_password_timeout_id;
|
|
|
|
gboolean good_password;
|
|
|
|
/* Communication with the passwd program */
|
|
int backend_pid;
|
|
|
|
int write_fd;
|
|
int read_fd;
|
|
|
|
FILE *write_stream;
|
|
FILE *read_stream;
|
|
|
|
} PasswordDialog;
|
|
|
|
enum
|
|
{
|
|
RESPONSE_APPLY = 1,
|
|
RESPONSE_CLOSE
|
|
};
|
|
|
|
static void passdlg_set_busy (PasswordDialog *dlg, gboolean busy);
|
|
|
|
#define REDRAW_NCHARS 1
|
|
|
|
static gboolean
|
|
wait_child (PasswordDialog *pdialog)
|
|
{
|
|
gint status, pid;
|
|
gchar *msg, *details, *title;
|
|
GladeXML *dialog;
|
|
GtkWidget *wmessage, *wbulb;
|
|
GtkWidget *wedialog;
|
|
|
|
dialog = pdialog->xml;
|
|
|
|
wmessage = WID ("message");
|
|
wbulb = WID ("bulb");
|
|
|
|
pid = waitpid (pdialog->backend_pid, &status, WNOHANG);
|
|
passdlg_set_busy (pdialog, FALSE);
|
|
|
|
if (pid > 0) {
|
|
|
|
if (WIFEXITED (status) && (WEXITSTATUS(status) == 0)) {
|
|
/* I need to quit here */
|
|
|
|
return FALSE;
|
|
} else if ((WIFEXITED (status)) && (WEXITSTATUS (status)) && (WEXITSTATUS(status) < 255)) {
|
|
|
|
msg = g_strdup_printf ("<b>%s</b>", _("Old password is incorrect, please retype it"));
|
|
|
|
gtk_label_set_markup (GTK_LABEL (wmessage), msg);
|
|
g_free (msg);
|
|
|
|
gtk_image_set_from_file (GTK_IMAGE (wbulb),
|
|
GNOMECC_DATA_DIR "/pixmaps/gnome-about-me-bulb-off.png");
|
|
|
|
|
|
return FALSE;
|
|
} else if ((WIFEXITED (status)) && (WEXITSTATUS (status)) && (WEXITSTATUS (status) == 255)) {
|
|
msg = g_strdup (_("System error has occurred"));
|
|
details = g_strdup (_("Could not run /usr/bin/passwd"));
|
|
title = g_strdup (_("Unable to launch backend"));
|
|
} else {
|
|
msg = g_strdup (_("Unexpected error has occurred"));
|
|
title = g_strdup (_("Unexpected error has occurred"));
|
|
details = NULL;
|
|
}
|
|
|
|
wedialog = eel_alert_dialog_new (NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
|
|
msg, NULL, title);
|
|
|
|
if (details != NULL)
|
|
eel_alert_dialog_set_details_label (EEL_ALERT_DIALOG (wedialog), details);
|
|
|
|
g_signal_connect (G_OBJECT (wedialog), "response",
|
|
G_CALLBACK (gtk_widget_destroy), NULL);
|
|
|
|
gtk_window_set_resizable (GTK_WINDOW (wedialog), FALSE);
|
|
gtk_widget_show (wedialog);
|
|
|
|
g_free (msg);
|
|
g_free (title);
|
|
g_free (details);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
is_string_complete (gchar *str, GSList *list)
|
|
{
|
|
GSList *elem;
|
|
|
|
if (strlen (str) == 0)
|
|
return FALSE;
|
|
|
|
for (elem = list; elem; elem = g_slist_next (elem))
|
|
if (g_strrstr (str, elem->data) != NULL) {
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static gchar*
|
|
read_everything (PasswordDialog *pdialog, gchar *needle, va_list ap)
|
|
{
|
|
GString *str = g_string_new ("");
|
|
GSList *list = NULL;
|
|
gchar*arg, *ptr;
|
|
int c;
|
|
|
|
list = g_slist_prepend (list, needle);
|
|
|
|
while ((arg = va_arg (ap, char*)) != NULL)
|
|
list = g_slist_prepend (list, arg);
|
|
|
|
va_end (ap);
|
|
|
|
while (!is_string_complete (str->str, list)) {
|
|
c = fgetc (pdialog->read_stream);
|
|
|
|
if (c != EOF)
|
|
g_string_append_c (str, c);
|
|
}
|
|
|
|
ptr = str->str;
|
|
g_string_free (str, FALSE);
|
|
|
|
return ptr;
|
|
}
|
|
|
|
static void
|
|
poll_backend (PasswordDialog *pdialog)
|
|
{
|
|
struct pollfd fd;
|
|
|
|
fd.fd = pdialog->read_fd;
|
|
fd.events = POLLIN || POLLPRI;
|
|
|
|
while (poll (&fd, 1, 100) <= 0) {
|
|
while (gtk_events_pending ())
|
|
gtk_main_iteration ();
|
|
}
|
|
}
|
|
|
|
static char *
|
|
read_from_backend_va (PasswordDialog *pdialog, gchar *needle, va_list ap)
|
|
{
|
|
poll_backend (pdialog);
|
|
return read_everything (pdialog, needle, ap);
|
|
}
|
|
|
|
static gchar*
|
|
read_from_backend (PasswordDialog *pdialog, gchar *needle, ...)
|
|
{
|
|
va_list ap;
|
|
|
|
va_start (ap, needle);
|
|
return read_from_backend_va (pdialog, needle, ap);
|
|
}
|
|
|
|
static void
|
|
write_to_backend (PasswordDialog *pdialog, char *str)
|
|
{
|
|
gint nread = 0;
|
|
int ret;
|
|
|
|
do {
|
|
ret = fputc (str [nread], pdialog->write_stream);
|
|
|
|
usleep (1000);
|
|
|
|
if (ret != EOF)
|
|
nread++;
|
|
|
|
/* ugly hack for redrawing UI */
|
|
if (nread % REDRAW_NCHARS == 0)
|
|
while (gtk_events_pending ())
|
|
gtk_main_iteration ();
|
|
} while (nread < strlen (str));
|
|
|
|
while (fflush (pdialog->write_stream) != 0);
|
|
}
|
|
|
|
static void
|
|
passdlg_set_busy (PasswordDialog *pdialog, gboolean busy)
|
|
{
|
|
GladeXML *dialog;
|
|
GtkWidget *toplevel;
|
|
GdkCursor *cursor = NULL;
|
|
GdkDisplay *display;
|
|
|
|
dialog = pdialog->xml;
|
|
toplevel = WID ("change-password");
|
|
|
|
display = gtk_widget_get_display (toplevel);
|
|
if (busy)
|
|
cursor = gdk_cursor_new_for_display (display, GDK_WATCH);
|
|
|
|
gdk_window_set_cursor (toplevel->window, cursor);
|
|
gdk_display_flush (display);
|
|
|
|
if (busy)
|
|
gdk_cursor_unref (cursor);
|
|
}
|
|
|
|
|
|
static gint
|
|
update_password (PasswordDialog *pdialog, gchar **msg)
|
|
{
|
|
GtkWidget *wopasswd, *wnpasswd, *wrnpasswd;
|
|
char *new_password;
|
|
char *retyped_password;
|
|
char *old_password;
|
|
gchar *s;
|
|
GladeXML *dialog;
|
|
gint retcode;
|
|
|
|
dialog = pdialog->xml;
|
|
|
|
wopasswd = WID ("old-password");
|
|
wnpasswd = WID ("new-password");
|
|
wrnpasswd = WID ("retyped-password");
|
|
|
|
retcode = 0;
|
|
|
|
/* */
|
|
old_password = g_strdup_printf ("%s\n", gtk_entry_get_text (GTK_ENTRY (wopasswd)));
|
|
new_password = g_strdup_printf ("%s\n", gtk_entry_get_text (GTK_ENTRY (wnpasswd)));
|
|
retyped_password = g_strdup_printf ("%s\n", gtk_entry_get_text (GTK_ENTRY (wrnpasswd)));
|
|
|
|
/* Set the busy cursor as this can be a long process */
|
|
passdlg_set_busy (pdialog, TRUE);
|
|
|
|
s = read_from_backend (pdialog, "assword: ", NULL);
|
|
g_free (s);
|
|
|
|
write_to_backend (pdialog, old_password);
|
|
|
|
/* New password */
|
|
s = read_from_backend (pdialog, "assword: ", "failure", "wrong", NULL);
|
|
if (g_strrstr (s, "failure") != NULL ||
|
|
g_strrstr (s, "wrong") != NULL) {
|
|
g_free (s);
|
|
return -1;
|
|
}
|
|
g_free (s);
|
|
|
|
write_to_backend (pdialog, new_password);
|
|
|
|
/* Retype password */
|
|
s = read_from_backend (pdialog, "assword: ", NULL);
|
|
g_free (s);
|
|
|
|
write_to_backend (pdialog, retyped_password);
|
|
|
|
s = read_from_backend (pdialog, "successfully", "short", "panlindrome", "simple", "similar", "wrapped", "recovered", "unchanged", "match", "1 numeric or special", NULL);
|
|
if (g_strrstr (s, "recovered") != NULL) {
|
|
retcode = -2;
|
|
} else if (g_strrstr (s, "short") != NULL) {
|
|
*msg = g_strdup (_("Password is too short"));
|
|
retcode = -3;
|
|
} else if (g_strrstr (s, "panlindrome") != NULL) {
|
|
*msg = g_strdup (_("Password is too simple"));
|
|
retcode = -3;
|
|
} else if (g_strrstr (s, "simple") != NULL) {
|
|
*msg = g_strdup (_("Password is too simple"));
|
|
retcode = -3;
|
|
} else if ((g_strrstr (s, "similar") != NULL) || (g_strrstr (s, "wrapped") != NULL)) {
|
|
*msg = g_strdup (_("Old and new passwords are too similar"));
|
|
retcode = -3;
|
|
} else if (g_strrstr (s, "1 numeric or special") != NULL) {
|
|
*msg = g_strdup (_("Must contain numeric or special character(s)"));
|
|
retcode = -3;
|
|
} else if ((g_strrstr (s, "unchanged") != NULL) ||
|
|
(g_strrstr (s, "match") != NULL)) {
|
|
kill (pdialog->backend_pid, SIGKILL);
|
|
*msg = g_strdup (_("Old and new password are the same"));
|
|
retcode = -3;
|
|
}
|
|
|
|
g_free (s);
|
|
|
|
return retcode;
|
|
}
|
|
|
|
#ifndef HAVE_FORKPTY
|
|
/*
|
|
// Emulation of the BSD function forkpty.
|
|
// Copied from rootsh (http://sourceforge.net/projects/rootsh) also
|
|
// under GPL license. Slightly modified to not copy terminal modes
|
|
// or window size from the parent to the child if NULL is passed in
|
|
// for termp or winp. The logic still sets the termp or winp values
|
|
// if passed in. When launching from the gnome-panel, there are no
|
|
// such values for the parent and attempting to copy them was causing
|
|
// a lengthy delay.
|
|
*/
|
|
#ifndef MASTERPTYDEV
|
|
# error you need to specify a master pty device
|
|
#endif
|
|
pid_t forkpty(int *amaster, char *name, struct termios *termp, struct winsize *winp) {
|
|
/*
|
|
// amaster A pointer to the master pty's file descriptor which
|
|
// will be set here.
|
|
//
|
|
// name If name is NULL, the name of the slave pty will be
|
|
// returned in name.
|
|
//
|
|
// termp If termp is not NULL, the terminal parameters
|
|
// of the slave will be set to the values in termp.
|
|
//
|
|
// winsize If winp is not NULL, the window size of the slave
|
|
// will be set to the values in winp.
|
|
//
|
|
// pid The process id of the forked child process.
|
|
//
|
|
// master The file descriptor of the master pty.
|
|
//
|
|
// slave The file descriptor of the slave pty.
|
|
//
|
|
// slavename The file name of the slave pty.
|
|
//
|
|
*/
|
|
pid_t pid;
|
|
int master, slave;
|
|
char *slavename;
|
|
|
|
/*
|
|
// Get a master pseudo-tty.
|
|
*/
|
|
if ((master = open (MASTERPTYDEV, O_RDWR)) < 0) {
|
|
perror (MASTERPTYDEV);
|
|
return (-1);
|
|
}
|
|
|
|
/*
|
|
// Set the permissions on the slave pty.
|
|
*/
|
|
if (grantpt (master) < 0) {
|
|
perror ("grantpt");
|
|
close (master);
|
|
return (-1);
|
|
}
|
|
|
|
/*
|
|
// Unlock the slave pty.
|
|
*/
|
|
if (unlockpt(master) < 0) {
|
|
perror ("unlockpt");
|
|
close (master);
|
|
return (-1);
|
|
}
|
|
|
|
/*
|
|
// Start a child process.
|
|
*/
|
|
if ((pid = fork ()) < 0) {
|
|
perror ("fork in forkpty");
|
|
close (master);
|
|
return (-1);
|
|
}
|
|
|
|
/*
|
|
// The child process will open the slave, which will become
|
|
// its controlling terminal.
|
|
*/
|
|
if (pid == 0) {
|
|
/*
|
|
// Get rid of our current controlling terminal.
|
|
*/
|
|
setsid ();
|
|
|
|
/*
|
|
// Get the name of the slave pseudo tty.
|
|
*/
|
|
if ((slavename = ptsname (master)) == NULL) {
|
|
perror ("ptsname");
|
|
close (master);
|
|
return (-1);
|
|
}
|
|
|
|
/*
|
|
// Open the slave pseudo tty.
|
|
*/
|
|
if ((slave = open(slavename, O_RDWR)) < 0) {
|
|
perror (slavename);
|
|
close (master);
|
|
return (-1);
|
|
}
|
|
|
|
#ifndef AIX_COMPAT
|
|
/*
|
|
// Push the pseudo-terminal emulation module.
|
|
*/
|
|
if (ioctl (slave, I_PUSH, "ptem") < 0) {
|
|
perror ("ioctl: ptem");
|
|
close (master);
|
|
close (slave);
|
|
return (-1);
|
|
}
|
|
|
|
/*
|
|
// Push the terminal line discipline module.
|
|
*/
|
|
if (ioctl (slave, I_PUSH, "ldterm") < 0) {
|
|
perror ("ioctl: ldterm");
|
|
close (master);
|
|
close (slave);
|
|
return (-1);
|
|
}
|
|
|
|
#ifdef HAVE_TTCOMPAT
|
|
/*
|
|
// Push the compatibility for older ioctl calls module (solaris).
|
|
*/
|
|
if (ioctl (slave, I_PUSH, "ttcompat") < 0) {
|
|
perror ("ioctl: ttcompat");
|
|
close (master);
|
|
close (slave);
|
|
return (-1);
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
/*
|
|
// Copy the caller's terminal modes to the slave pty.
|
|
*/
|
|
if (termp != NULL) {
|
|
if (tcsetattr (slave, TCSANOW, termp) < 0) {
|
|
perror ("tcsetattr: slave pty");
|
|
close (master);
|
|
close (slave);
|
|
return (-1);
|
|
}
|
|
}
|
|
|
|
/*
|
|
// Set the slave pty window size to the caller's size.
|
|
*/
|
|
if (winp != NULL) {
|
|
if (ioctl (slave, TIOCSWINSZ, winp) < 0) {
|
|
perror ("ioctl: slave winsz");
|
|
close (master);
|
|
close (slave);
|
|
return (-1);
|
|
}
|
|
}
|
|
|
|
/*
|
|
// Close the master pty.
|
|
// No need for this in the slave process.
|
|
*/
|
|
close (master);
|
|
|
|
/*
|
|
// Set the slave to be our standard input, output and error output.
|
|
// Then get rid of the original file descriptor.
|
|
*/
|
|
dup2 (slave, 0);
|
|
dup2 (slave, 1);
|
|
dup2 (slave, 2);
|
|
close (slave);
|
|
|
|
/*
|
|
// If the caller wants it, give him back the slave pty's name.
|
|
*/
|
|
if (name != NULL)
|
|
strcpy (name, slavename);
|
|
|
|
return(0);
|
|
|
|
} else {
|
|
/*
|
|
// Return the slave pty device name if caller wishes so.
|
|
*/
|
|
if (name != NULL) {
|
|
if ((slavename = ptsname (master)) == NULL) {
|
|
perror ("ptsname");
|
|
close (master);
|
|
return (-1);
|
|
}
|
|
strcpy (name, slavename);
|
|
}
|
|
|
|
/*
|
|
// Return the file descriptor for communicating with the process
|
|
// to the caller.
|
|
*/
|
|
*amaster = master;
|
|
return (pid);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
static gint
|
|
spawn_passwd (PasswordDialog *pdialog)
|
|
{
|
|
char *args[2];
|
|
int p[2];
|
|
|
|
/* Prepare the execution environment of passwd */
|
|
args[0] = "/usr/bin/passwd";
|
|
args[1] = NULL;
|
|
|
|
pipe (p);
|
|
pdialog->backend_pid = forkpty (&pdialog->write_fd, NULL, NULL, NULL);
|
|
if (pdialog->backend_pid < 0) {
|
|
g_warning ("could not fork to backend");
|
|
return -1;
|
|
} else if (pdialog->backend_pid == 0) {
|
|
dup2 (p[1], 1);
|
|
dup2 (p[1], 2);
|
|
close (p[0]);
|
|
|
|
unsetenv("LC_ALL");
|
|
unsetenv("LC_MESSAGES");
|
|
unsetenv("LANG");
|
|
unsetenv("LANGUAGE");
|
|
|
|
execv (args[0], args);
|
|
exit (255);
|
|
} else {
|
|
close (p[1]);
|
|
pdialog->read_fd = p[0];
|
|
pdialog->timeout_id = g_timeout_add (4000, (GSourceFunc) wait_child, pdialog);
|
|
|
|
pdialog->read_stream = fdopen (pdialog->read_fd, "r");;
|
|
pdialog->write_stream = fdopen (pdialog->write_fd, "w");
|
|
|
|
setvbuf (pdialog->read_stream, NULL, _IONBF, 0);
|
|
fcntl (pdialog->read_fd, F_SETFL, 0);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static gboolean
|
|
passdlg_check_password_timeout_cb (PasswordDialog *pdialog)
|
|
{
|
|
const gchar *password;
|
|
const gchar *retyped_password;
|
|
char *msg;
|
|
gboolean good_password;
|
|
|
|
GtkWidget *wbulb, *wok, *wmessage;
|
|
GtkWidget *wnpassword, *wrnpassword;
|
|
GladeXML *dialog;
|
|
|
|
dialog = pdialog->xml;
|
|
|
|
wnpassword = WID ("new-password");
|
|
wrnpassword = WID ("retyped-password");
|
|
wmessage = WID ("message");
|
|
wbulb = WID ("bulb");
|
|
wok = WID ("ok");
|
|
|
|
password = gtk_entry_get_text (GTK_ENTRY (wnpassword));
|
|
retyped_password = gtk_entry_get_text (GTK_ENTRY (wrnpassword));
|
|
|
|
if (strlen (password) == 0 || strlen (retyped_password) == 0) {
|
|
gtk_image_set_from_file (GTK_IMAGE (wbulb),
|
|
GNOMECC_DATA_DIR "/pixmaps/gnome-about-me-bulb-off.png");
|
|
msg = g_strconcat ("<b>", _("Please type the passwords."), "</b>", NULL);
|
|
gtk_label_set_markup (GTK_LABEL (wmessage), msg);
|
|
g_free (msg);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if (strcmp (password, retyped_password) != 0) {
|
|
msg = g_strconcat ("<b>", _("Please type the password again, it is wrong."), "</b>", NULL);
|
|
good_password = FALSE;
|
|
} else {
|
|
msg = g_strconcat ("<b>", _("Click on Change Password to change the password."), "</b>", NULL);
|
|
good_password = TRUE;
|
|
}
|
|
|
|
if (good_password && pdialog->good_password == FALSE) {
|
|
gtk_image_set_from_file (GTK_IMAGE (wbulb),
|
|
GNOMECC_DATA_DIR "/pixmaps/gnome-about-me-bulb-on.png");
|
|
gtk_widget_set_sensitive (wok, TRUE);
|
|
} else if (good_password == FALSE && pdialog->good_password == TRUE) {
|
|
gtk_image_set_from_file (GTK_IMAGE (wbulb),
|
|
GNOMECC_DATA_DIR "/pixmaps/gnome-about-me-bulb-off.png");
|
|
gtk_widget_set_sensitive (wok, FALSE);
|
|
}
|
|
|
|
pdialog->good_password = good_password;
|
|
|
|
gtk_label_set_markup (GTK_LABEL (wmessage), msg);
|
|
g_free (msg);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
static void
|
|
passdlg_check_password (GtkEntry *entry, PasswordDialog *pdialog)
|
|
{
|
|
if (pdialog->check_password_timeout_id) {
|
|
g_source_remove (pdialog->check_password_timeout_id);
|
|
}
|
|
|
|
pdialog->check_password_timeout_id =
|
|
g_timeout_add (500, (GSourceFunc) passdlg_check_password_timeout_cb, pdialog);
|
|
|
|
}
|
|
|
|
static gint
|
|
passdlg_process_response (PasswordDialog *pdialog, gint response_id)
|
|
{
|
|
GladeXML *dialog;
|
|
GtkWidget *wmessage, *wbulb;
|
|
gchar *msg, *msgerr;
|
|
gint ret;
|
|
|
|
dialog = pdialog->xml;
|
|
|
|
wmessage = WID ("message");
|
|
wbulb = WID ("bulb");
|
|
|
|
msgerr = NULL;
|
|
|
|
if (response_id == GTK_RESPONSE_OK) {
|
|
ret = spawn_passwd (pdialog);
|
|
if (ret < 0)
|
|
return 1;
|
|
|
|
ret = update_password (pdialog, &msgerr);
|
|
passdlg_set_busy (pdialog, FALSE);
|
|
|
|
/* No longer need the wait_child fallback, remove the timeout */
|
|
g_source_remove (pdialog->timeout_id);
|
|
|
|
if (ret == -1) {
|
|
msg = g_strdup_printf ("<b>%s</b>", _("Old password is incorrect, please retype it"));
|
|
gtk_label_set_markup (GTK_LABEL (wmessage), msg);
|
|
g_free (msg);
|
|
|
|
gtk_image_set_from_file (GTK_IMAGE (wbulb),
|
|
GNOMECC_DATA_DIR "/pixmaps/gnome-about-me-bulb-off.png");
|
|
|
|
return -1;
|
|
} else if (ret == -3) {
|
|
msg = g_strdup_printf ("<b>%s</b>", msgerr);
|
|
gtk_label_set_markup (GTK_LABEL (wmessage), msg);
|
|
g_free (msg);
|
|
|
|
gtk_image_set_from_file (GTK_IMAGE (wbulb),
|
|
GNOMECC_DATA_DIR "/pixmaps/gnome-about-me-bulb-off.png");
|
|
|
|
g_free (msgerr);
|
|
|
|
return -1;
|
|
}
|
|
|
|
/* This is the standard way of returning from the dialog with passwd
|
|
* If we return this way we can safely kill passwd as it has completed
|
|
* its task. In case of problems we still have the wait_child fallback
|
|
*/
|
|
fclose (pdialog->write_stream);
|
|
fclose (pdialog->read_stream);
|
|
|
|
close (pdialog->read_fd);
|
|
close (pdialog->write_fd);
|
|
|
|
kill (pdialog->backend_pid, 9);
|
|
|
|
if (ret == 0)
|
|
return 1;
|
|
} else {
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
void
|
|
gnome_about_me_password (GtkWindow *parent)
|
|
{
|
|
PasswordDialog *pdialog;
|
|
GtkWidget *wpassdlg;
|
|
GladeXML *dialog;
|
|
gint result;
|
|
|
|
pdialog = g_new0 (PasswordDialog, 1);
|
|
|
|
dialog = glade_xml_new (GNOMECC_DATA_DIR "/interfaces/gnome-about-me.glade", "change-password", NULL);
|
|
|
|
pdialog->xml = dialog;
|
|
|
|
wpassdlg = WID ("change-password");
|
|
capplet_set_icon (wpassdlg, "user-info");
|
|
|
|
pdialog->good_password = FALSE;
|
|
|
|
g_signal_connect (G_OBJECT (WID ("new-password")), "changed",
|
|
G_CALLBACK (passdlg_check_password), pdialog);
|
|
g_signal_connect (G_OBJECT (WID ("retyped-password")), "changed",
|
|
G_CALLBACK (passdlg_check_password), pdialog);
|
|
|
|
gtk_image_set_from_file (GTK_IMAGE (WID ("bulb")), GNOMECC_DATA_DIR "/pixmaps/gnome-about-me-bulb-off.png");
|
|
gtk_widget_set_sensitive (WID ("ok"), FALSE);
|
|
|
|
gtk_window_set_resizable (GTK_WINDOW (wpassdlg), FALSE);
|
|
gtk_window_set_transient_for (GTK_WINDOW (wpassdlg), GTK_WINDOW (parent));
|
|
gtk_widget_show_all (wpassdlg);
|
|
|
|
|
|
do {
|
|
result = gtk_dialog_run (GTK_DIALOG (wpassdlg));
|
|
result = passdlg_process_response (pdialog, result);
|
|
} while (result <= 0);
|
|
|
|
gtk_widget_destroy (wpassdlg);
|
|
g_free (pdialog);
|
|
}
|