Logo Search packages:      
Sourcecode: ldm version File versions  Download package

greeter.c

/*
 * LTSP Graphical GTK Greeter
 * Copyright (2007) Oliver Grawert <ogra@ubuntu.com>, Canonical Ltd.
 * Code Licensed under GPL v2
 */

#define _GNU_SOURCE

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <gtk/gtk.h>
#include <glib.h>
#include <string.h>
#include <sys/utsname.h>
#include <sys/socket.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>

#include <greeter.h>


#include <config.h>

#include <libintl.h>
#include <locale.h>
#define _(text) gettext(text)

/* 
 *  Make sure that StatusMessages can accommodate many lines of text - auto scrollbars?
 */
GtkWidget *UserPrompt;          /* prompt area before the entry */
GtkWidget *StatusMessages;      /* Status msg area below entry */
GtkWidget *entry;               /* entry box */
GtkWidget *guestbox;
GtkWidget *timeoutbox;
gboolean timeout_enabled;

GHashTable *ldminfo_hash = NULL;
GList *host_list = NULL;
GIOChannel *g_stdout;           /* stdout io channel */
char ldm_theme_dir[512];

int allowguest;
gint timeout_left;

char *
ldm_theme_file(char * file)
{
    static char path[512];
    strcpy(path, ldm_theme_dir);
    strcat(path, file);
    return path;
}

static void
destroy(GtkWidget * widget, gpointer data)
{
    gtk_main_quit();
}

static void
halt(GtkWidget * widget, gpointer data)
{
    GError **error = NULL;
    g_spawn_command_line_async("/sbin/poweroff -fp", error);
}

static void
reboot(GtkWidget * widget, gpointer data)
{
    GError **error = NULL;
    g_spawn_command_line_async("/sbin/reboot -fp", error);
}

gboolean
update_time(GtkWidget * label)
{
    gchar *timestring = 0;
    time_t timet;
    struct tm *timePtr;

    timet = time(NULL);
    timePtr = localtime(&timet);

    // use 12 hour clock format if LDM_12HOURCLOCK is set to true
    if (ldm_getenv_bool("LDM_12HOURCLOCK")) {
        timestring = g_strdup_printf("%.2d:%.2d ",
                                   (timePtr->tm_hour % 12) ? (timePtr->tm_hour % 12) : 12,
                                   timePtr->tm_min);
    }
    else {
        timestring = g_strdup_printf("%.2d:%.2d ",
                                   timePtr->tm_hour, timePtr->tm_min);
    }

    gtk_label_set_markup((GtkLabel *) label, timestring);

    g_free(timestring);

    return TRUE;
}

gboolean
update_timeout(GtkWidget * label)
{
    gchar *string;
    int entry_length;
    entry_length = strlen(gtk_entry_get_text((GtkEntry *)entry));
    if(entry_length == 0 && timeout_enabled) {
        if (timeout_left > 1){
            timeout_left--;
        } else if (timeout_left == 1) {
            g_io_channel_write_chars(g_stdout, g_strdup_printf("@GUEST@\n"), -1, NULL, NULL);
            g_io_channel_flush(g_stdout, NULL);
            timeout_left = 0;
            timeout_enabled = FALSE;
        } else if (timeout_left == 0){
            timeout_left = atoi(getenv("LDM_TIMEOUT_TIME"));
        }
        string = g_strdup_printf(_("Automatic login in %d seconds"), timeout_left);
        gtk_label_set_markup((GtkLabel *) label, string);
        g_free(string);
        gtk_widget_show(timeoutbox);
    } else {
        timeout_left = 0;
        gtk_widget_hide(timeoutbox);
    }
}

void
destroy_popup(GtkWidget * widget, GtkWidget * popup)
{
    gtk_widget_destroy(popup);
    return;
}

gboolean
handle_command(GIOChannel * io_input)
{
    GString *buf;

    buf = g_string_new("");

    g_io_channel_read_line_string(io_input, buf, NULL, NULL);

    if (!g_strncasecmp(buf->str, "msg", 3)) {
        gchar **split_buf;
        split_buf = g_strsplit(buf->str, " ", 2);
        gtk_label_set_markup((GtkLabel *) StatusMessages, split_buf[1]);
        g_strfreev(split_buf);
        gtk_entry_set_editable(GTK_ENTRY(entry), FALSE);
    } else if (!g_strncasecmp(buf->str, "quit", 4)) {
        GdkCursor *cursor;
        cursor = gdk_cursor_new(GDK_WATCH);
        gdk_window_set_cursor(gdk_get_default_root_window(), cursor);
        gtk_main_quit();
    } else if (!g_strncasecmp(buf->str, "prompt", 6)) {
        gchar **split_buf;
        split_buf = g_strsplit(buf->str, " ", 2);
        gtk_label_set_markup((GtkLabel *) UserPrompt, split_buf[1]);
        g_strfreev(split_buf);
    } else if (!g_strncasecmp(buf->str, "userid", 6)) {
        gtk_widget_show(guestbox);
        timeout_enabled = ldm_getenv_bool("LDM_TIMEOUT_ENABLED");
        if(timeout_enabled) {
            gtk_widget_show(timeoutbox);
        }
        gtk_entry_set_visibility(GTK_ENTRY(entry), TRUE);
        gtk_entry_set_editable(GTK_ENTRY(entry), TRUE);
    } else if (!g_strncasecmp(buf->str, "passwd", 6)) {
        timeout_enabled = FALSE;
        timeout_left = 0;
        gtk_widget_hide(timeoutbox);
        gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE);
        gtk_entry_set_editable(GTK_ENTRY(entry), TRUE);
    } else if (!g_strncasecmp(buf->str, "hostname", 8)) {
        gchar *hoststr;
        update_selected_host();
        hoststr = g_strdup_printf("%s\n", host);
        g_io_channel_write_chars(g_stdout, hoststr, -1, NULL, NULL);
        g_io_channel_flush(g_stdout, NULL);
        g_free(hoststr);
    } else if (!g_strncasecmp(buf->str, "language", 8)) {
        gchar *langstr;
        update_selected_lang();
        langstr = g_strdup_printf("%s\n", language);
        g_io_channel_write_chars(g_stdout, langstr, -1, NULL, NULL);
        g_io_channel_flush(g_stdout, NULL);
        g_free(langstr);
    } else if (!g_strncasecmp(buf->str, "session", 7)) {
        gchar *sessstr;
        update_selected_sess();
        sessstr = g_strdup_printf("%s\n", session);
        g_io_channel_write_chars(g_stdout, sessstr, -1, NULL, NULL);
        g_io_channel_flush(g_stdout, NULL);
        g_free(sessstr);
    }

    g_string_free(buf, TRUE);
    return TRUE;
}

char *
get_sysname(void)
{
    struct utsname name;
    char *node;

    if (uname(&name) == 0) {
        node = strdup(name.nodename);
        return node;
    }
    return NULL;
}

static void
handle_guestbutton(GtkButton * entry, GdkWindow * window)
{
    g_io_channel_write_chars(g_stdout, g_strdup_printf("@GUEST@\n"), -1, NULL, NULL);
    g_io_channel_flush(g_stdout, NULL);
}

static void
handle_entry(GtkEntry * entry, GdkWindow * window)
{
    gchar *entrystr;

    if(gtk_entry_get_visibility(GTK_ENTRY(entry)))
        g_io_channel_write_chars(g_stdout, g_strdup_printf("@NOTGUEST@\n"), -1, NULL, NULL);
    entrystr = g_strdup_printf("%s\n", gtk_entry_get_text(entry));
    g_io_channel_write_chars(g_stdout, entrystr, -1, NULL, NULL);
    g_io_channel_flush(g_stdout, NULL);
    g_free(entrystr);
    gtk_entry_set_text(entry, "");
}

static void
popup_menu(GtkWidget * widget, GtkWindow * window)
{
    GtkWidget *menu, *lang_item, *sess_item, *host_item, *quit_item,
        *reboot_item;
    GtkWidget *sep, *langico, *sessico, *hostico, *rebootico, *haltico;

    menu = gtk_menu_new();

    lang_item =
        gtk_image_menu_item_new_with_mnemonic(_("Select _Language ..."));
    langico = gtk_image_new_from_file(ldm_theme_file("/language.png"));
    gtk_image_menu_item_set_image((GtkImageMenuItem *) lang_item, langico);

    sess_item =
        gtk_image_menu_item_new_with_mnemonic(_("Select _Session ..."));
    sessico = gtk_image_new_from_file(ldm_theme_file("/session.png"));
    gtk_image_menu_item_set_image((GtkImageMenuItem *) sess_item, sessico);

    host_item =
        gtk_image_menu_item_new_with_mnemonic(_("Select _Host ..."));
    hostico = gtk_image_new_from_file(ldm_theme_file("/host.png"));
    gtk_image_menu_item_set_image((GtkImageMenuItem *) host_item, hostico);

    sep = gtk_separator_menu_item_new();
    reboot_item = gtk_image_menu_item_new_with_mnemonic(_("_Reboot"));
    rebootico = gtk_image_new_from_file(ldm_theme_file("/reboot.png"));
    gtk_image_menu_item_set_image((GtkImageMenuItem *) reboot_item,
                                  rebootico);
    quit_item = gtk_image_menu_item_new_with_mnemonic(_("Shut_down"));
    haltico = gtk_image_new_from_file(ldm_theme_file("/shutdown.png"));
    gtk_image_menu_item_set_image((GtkImageMenuItem *) quit_item, haltico);

    g_signal_connect_swapped(G_OBJECT(quit_item), "activate",
                             G_CALLBACK(halt), NULL);
    g_signal_connect_swapped(G_OBJECT(reboot_item), "activate",
                             G_CALLBACK(reboot), NULL);
    g_signal_connect_swapped(G_OBJECT(lang_item), "activate",
                             G_CALLBACK(langwin), window);
    g_signal_connect_swapped(G_OBJECT(sess_item), "activate",
                             G_CALLBACK(sesswin), window);
    g_signal_connect_swapped(G_OBJECT(host_item), "activate",
                             G_CALLBACK(hostwin), window);


    gtk_menu_shell_append(GTK_MENU_SHELL(menu), lang_item);
    gtk_menu_shell_append(GTK_MENU_SHELL(menu), sess_item);
    if (g_hash_table_size(ldminfo_hash) > 1)
        gtk_menu_shell_append(GTK_MENU_SHELL(menu), host_item);
    gtk_menu_shell_append(GTK_MENU_SHELL(menu), sep);
    gtk_menu_shell_append(GTK_MENU_SHELL(menu), reboot_item);
    gtk_menu_shell_append(GTK_MENU_SHELL(menu), quit_item);

    gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
                   0, gtk_get_current_event_time());

    gtk_widget_show_all(menu);
    gtk_menu_reposition(GTK_MENU(menu));

    return;
}

/*
 * scopy()
 *
 * Copy a string.  Used to move data in and out of our ldminfo structure.
 * Note: if the source string is null, or points to a valid string of '\0',
 * both result in a dest string length of 0.
 */

char *
scopy(char *dest, char *source)
{
    if (!source)
        *dest = '\0';
    else {
        strncpy(dest, source, MAXSTRSZ - 1);
        *(dest + MAXSTRSZ - 1) = '\0';     /* ensure null termination */
    }

    return dest;
}

void
setup_keyboard_layout()
{
    char *argv[32];
    char layout[MAXSTRSZ];
    char model[MAXSTRSZ];
    char rules[MAXSTRSZ];
    char options[MAXSTRSZ];
    char variant[MAXSTRSZ];
    int i = 0;
    int pid;

    argv[i++] = "/usr/bin/setxkbmap";
    scopy(layout, getenv("XKBLAYOUT"));
    if (! layout[0] == '\0') {
        argv[i++] = "-layout";
        argv[i++] = layout;
    }
    scopy(model, getenv("XKBMODEL"));
    if (! model[0] == '\0') {
        argv[i++] = "-model";
        argv[i++] = model;
    }
    scopy(rules, getenv("XKBRULES"));
    if (! rules[0] == '\0') {
        argv[i++] = "-rules";
        argv[i++] = rules;
    }
    scopy(options, getenv("XKBOPTIONS"));
    if (! options[0] == '\0') {
        argv[i++] = "-option";
        argv[i++] = options;
    }
    scopy(variant, getenv("XKBVARIANT"));
    if (! variant[0] == '\0') {
        argv[i++] = "-variant";
        argv[i++] = variant;
    }
    argv[i++] = NULL;

    // Skip setxkbmap if no parameters were specified
    if (i > 2) {
        g_spawn_sync(NULL,argv,NULL,G_SPAWN_STDOUT_TO_DEV_NULL|G_SPAWN_STDERR_TO_DEV_NULL,NULL,NULL,NULL,NULL,NULL,NULL);
    }
    return;
}

int
main(int argc, char *argv[])
{
    int pw, ph, spheight, w, h;
    const char *hoststring = 0;

    gint lw, lh;

    GdkCursor *normcursor, *busycursor;
    GtkWidget *window, *syslabel, *logo, *EntryBox, *timelabel;
    GtkWidget *GuestButton, *StatusBarBox, *spacer, *guestspacer1, *guestspacer2, *vbox, *vbox2, *hbox;
    GtkWidget *timeoutspacer1, *timeoutspacer2, *timeoutlabel;
    GtkWidget *entryspacer1, *entryspacer2;
    GtkButton *optionbutton, *cancelbutton;
    GdkWindow *root;
    GdkPixbuf *rawpic, *pix;
    GdkPixmap *pic;
    GdkBitmap *mask;
    gint width, height;
    GIOChannel *g_stdin;

    char * ldm_theme;

#ifdef ENABLE_NLS
     setlocale (LC_ALL, "");
     bindtextdomain (GETTEXT_PACKAGE, LOCALE_DIR);
     bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
     textdomain (GETTEXT_PACKAGE);
#endif

    gtk_init(&argc, &argv);

    *ldm_theme_dir='\0';
    ldm_theme = getenv("LDM_THEME");

    if (ldm_theme)
    {
        char temp[512];
        strcpy(temp, ldm_theme);
        if(*temp != '/')
            strcpy(ldm_theme_dir, LDM_THEME_DIR);
        strcat(ldm_theme_dir, temp);
    }
    else
    {
        strcpy(ldm_theme_dir, LDM_THEME_DIR);
        strcat(ldm_theme_dir, "default");
    }

    allowguest = ldm_getenv_bool("LDM_GUESTLOGIN");
    gtk_rc_add_default_file(ldm_theme_file("/greeter-gtkrc"));

    /* Initialize information about hosts */
    ldminfo_init(&ldminfo_hash, &host_list, getenv("LDM_SERVER"));

    normcursor = gdk_cursor_new(GDK_LEFT_PTR);
    busycursor = gdk_cursor_new(GDK_WATCH);

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(destroy),
                     NULL);

    root = gdk_get_default_root_window();

    gdk_window_set_cursor(root, busycursor);
    gdk_drawable_get_size(root, &width, &height);

    pw = width;
    ph = height;
    w = width;
    h = height;

    logo = gtk_image_new_from_file(ldm_theme_file("/logo.png"));

    pix = gtk_image_get_pixbuf((GtkImage *) logo);
    lw = gdk_pixbuf_get_width(pix);
    lh = gdk_pixbuf_get_height(pix);

    spheight = (height / 4) - (lh / 2);

    rawpic = gdk_pixbuf_new_from_file_at_scale(ldm_theme_file("/bg.png"),
                                               pw, ph, FALSE, NULL);
    gdk_pixbuf_render_pixmap_and_mask(rawpic, &pic, &mask, 0);
    gdk_pixbuf_unref(rawpic);

    gtk_widget_set_app_paintable(window, TRUE);
    gtk_widget_set_size_request(window, w, h);
    gtk_widget_realize(window);
    gdk_window_set_back_pixmap((GdkWindow *) window->window, pic, 0);
    gtk_window_set_decorated((GtkWindow *) window, FALSE);

    vbox = gtk_vbox_new(FALSE, 5);
    vbox2 = gtk_vbox_new(FALSE, 0);
    EntryBox = gtk_hbox_new(FALSE, 5);
    hbox = gtk_hbox_new(FALSE, 0);

    StatusBarBox = gtk_hbox_new(FALSE, 0);

    optionbutton =
        (GtkButton *) gtk_button_new_from_stock("gtk-preferences");
    gtk_button_set_relief(optionbutton, GTK_RELIEF_NONE);
    gtk_button_set_focus_on_click((GtkButton *) optionbutton, FALSE);

    g_signal_connect(G_OBJECT(optionbutton), "clicked",
                     G_CALLBACK(popup_menu), window);

    /*
     * Cancel button 
     */

    cancelbutton =
        (GtkButton *) gtk_button_new_from_stock(GTK_STOCK_CANCEL);
    gtk_button_set_relief(cancelbutton, GTK_RELIEF_NONE);
    gtk_button_set_focus_on_click((GtkButton *) cancelbutton, FALSE);

    g_signal_connect(G_OBJECT(cancelbutton), "clicked",
                     G_CALLBACK(destroy), window);

    syslabel = gtk_label_new("");
    timelabel = gtk_label_new("");
    hoststring =
        g_strdup_printf("<b>%s (%s) //</b>", get_sysname(), getenv("LDMINFO_IPADDR"));
    gtk_label_set_markup((GtkLabel *) syslabel, hoststring);
    update_time(timelabel);

    g_timeout_add(30000, (GSourceFunc) update_time, timelabel);

    gtk_box_pack_start(GTK_BOX(StatusBarBox),
                       GTK_WIDGET(optionbutton), FALSE, FALSE, 5);
    /*gtk_box_pack_start(GTK_BOX(StatusBarBox),
                       GTK_WIDGET(cancelbutton), FALSE, FALSE, 5);*/
    gtk_box_pack_end(GTK_BOX(StatusBarBox),
                     GTK_WIDGET(timelabel), FALSE, FALSE, 5);
    gtk_box_pack_end(GTK_BOX(StatusBarBox),
                     GTK_WIDGET(syslabel), FALSE, FALSE, 0);

    UserPrompt = gtk_label_new("");
    spacer = gtk_label_new("");

    if (lw < 180)
        lw = 180;

    gtk_misc_set_alignment((GtkMisc *) UserPrompt, 1, 0.5);
    gtk_widget_set_size_request(UserPrompt, (lw / 2), 0);

    StatusMessages = gtk_label_new("");
    entry = gtk_entry_new();
    gtk_entry_set_width_chars(GTK_ENTRY(entry), 12);
    g_signal_connect(G_OBJECT(entry), "activate",
                     G_CALLBACK(handle_entry), root);

    timeout_enabled = ldm_getenv_bool("LDM_TIMEOUT_ENABLED");
    timeout_left = 0;
    timeout_left = 0;
    timeoutspacer1 = gtk_label_new("");
    timeoutspacer2 = gtk_label_new("");
    timeoutlabel = gtk_label_new("");
    gtk_box_pack_start(GTK_BOX(vbox), timeoutbox, FALSE, FALSE, 0);
    timeoutbox = gtk_hbox_new(FALSE, 0);
    gtk_box_pack_start(GTK_BOX(timeoutbox), timeoutspacer1, TRUE, FALSE, 0);
    gtk_box_pack_start(GTK_BOX(timeoutbox), timeoutlabel, FALSE, FALSE, 0);
    gtk_box_pack_start(GTK_BOX(timeoutbox), timeoutspacer2, TRUE, FALSE, 0);
    g_timeout_add(1000, (GSourceFunc) update_timeout, timeoutlabel);

    guestspacer1 = gtk_label_new("");
    guestspacer2 = gtk_label_new("");
    GuestButton = gtk_button_new_with_label (_("Login as Guest"));
    g_signal_connect(G_OBJECT(GuestButton), "clicked",
        G_CALLBACK(handle_guestbutton), root);
    gtk_button_set_relief((GtkButton *)GuestButton, GTK_RELIEF_NONE);
    gtk_button_set_focus_on_click((GtkButton *)GuestButton, FALSE);
    guestbox = gtk_hbox_new(FALSE, 0);
    gtk_box_pack_start(GTK_BOX(guestbox), guestspacer1, TRUE, FALSE, 0);
    gtk_box_pack_start(GTK_BOX(guestbox), GuestButton, FALSE, FALSE, 0);
    gtk_box_pack_start(GTK_BOX(guestbox), guestspacer2, TRUE, FALSE, 0);

    entryspacer1 = gtk_label_new("");
    entryspacer2 = gtk_label_new("");
    gtk_box_pack_start(GTK_BOX(EntryBox), entryspacer1, TRUE, FALSE, 0);
    gtk_box_pack_start(GTK_BOX(EntryBox), UserPrompt, FALSE, FALSE, 0);
    gtk_box_pack_start(GTK_BOX(EntryBox), entry, FALSE, FALSE, 0);
    gtk_box_pack_start(GTK_BOX(EntryBox), entryspacer2, TRUE, FALSE, 0);

    gtk_box_pack_start(GTK_BOX(vbox), spacer, FALSE, FALSE, spheight);
    gtk_box_pack_start(GTK_BOX(vbox), logo, FALSE, FALSE, 5);
    gtk_box_pack_start(GTK_BOX(vbox), EntryBox, TRUE, FALSE, 0);
    if(allowguest) gtk_box_pack_start(GTK_BOX(vbox), guestbox, FALSE, FALSE, 0);
    gtk_box_pack_start(GTK_BOX(vbox), timeoutbox, FALSE, FALSE, 0);
    gtk_box_pack_start(GTK_BOX(vbox), StatusMessages, TRUE, FALSE, 0);
    gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, FALSE, 0);
    gtk_box_pack_start(GTK_BOX(vbox2), hbox, FALSE, FALSE, 0);
    gtk_box_pack_end(GTK_BOX(vbox2), StatusBarBox, FALSE, FALSE, 5);

    gtk_container_add(GTK_CONTAINER(window), vbox2);

    gtk_widget_show_all(window);

    gdk_window_set_cursor(root, normcursor);

    /*
     * Start listening to stdin
     */

    g_stdin = g_io_channel_unix_new(STDIN_FILENO);      /* listen to stdin */
    g_stdout = g_io_channel_unix_new(STDOUT_FILENO);
    g_io_add_watch(g_stdin, G_IO_IN, (GIOFunc) handle_command, g_stdin);

    setup_keyboard_layout();
    gtk_main();

    return 0;
}

Generated by  Doxygen 1.6.0   Back to index