X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=main.c;fp=main.c;h=3a49fe75d6e81f67a1a08e46551e6ea1141e6807;hb=4907eb0f04018c7032857e298c1c75014851c10e;hp=cf37b318c0d0ef9c38733502b1699796a151ba2d;hpb=0b9477affd8b7978768ee76bc5631adbec3a2dcf;p=ovirt-viewer.git diff --git a/main.c b/main.c index cf37b31..3a49fe7 100644 --- a/main.c +++ b/main.c @@ -60,6 +60,14 @@ static void login_to_wui (GtkWidget *, gpointer); static gboolean delete_event (GtkWidget *widget, GdkEvent *event, gpointer data); static void destroy (GtkWidget *widget, gpointer data); static void clear_connectmenu (void); +static void help_about (GtkWidget *menu); +static void viewer_shutdown (GtkWidget *src, void *dummy, GtkWidget *vnc); +static void viewer_quit (GtkWidget *src, GtkWidget *vnc); +static void viewer_connected (GtkWidget *vnc); +static void viewer_initialized (GtkWidget *vnc, GtkWidget *data); +static void viewer_disconnected (GtkWidget *vnc); +static void viewer_credential (GtkWidget *vnc, GValueArray *credList); +static int viewer_open_tunnel_ssh (const char *sshhost, int sshport, const char *sshuser, int vncport); /* For any widgets accessed from multiple functions. */ static GtkWidget *window; @@ -220,6 +228,7 @@ start_ui (void) GtkWidget *windmenu; GtkWidget *help; GtkWidget *helpmenu; + GtkWidget *about; GtkWidget *ca_vbox; GtkWidget *ca_hbox; GtkWidget *ca_label; @@ -291,6 +300,10 @@ start_ui (void) helpmenu = gtk_menu_new (); gtk_menu_item_set_submenu (GTK_MENU_ITEM (help), helpmenu); + about = gtk_image_menu_item_new_from_stock(GTK_STOCK_ABOUT, NULL); + gtk_menu_append(GTK_MENU(helpmenu), about); + g_signal_connect(about, "activate", GTK_SIGNAL_FUNC (help_about), NULL); + gtk_menu_bar_append (GTK_MENU_BAR (menubar), connectitem); gtk_menu_bar_append (GTK_MENU_BAR (menubar), view); gtk_menu_bar_append (GTK_MENU_BAR (menubar), sendkey); @@ -408,6 +421,42 @@ destroy (GtkWidget *widget, gpointer data) } static void +help_about (GtkWidget *menu) +{ + GtkWidget *about; + const char *authors[] = { + "Richard W.M. Jones ", + "Daniel P. Berrange ", + NULL + }; + + about = gtk_about_dialog_new(); + + gtk_about_dialog_set_name(GTK_ABOUT_DIALOG(about), "oVirt Viewer"); + gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(about), VERSION); + gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(about), "http://ovirt.org/"); + gtk_about_dialog_set_website_label(GTK_ABOUT_DIALOG(about), "oVirt website"); + gtk_about_dialog_set_authors(GTK_ABOUT_DIALOG(about), authors); + gtk_about_dialog_set_license(GTK_ABOUT_DIALOG(about), + "This program is free software; you can redistribute it and/or modify\n" \ + "it under the terms of the GNU General Public License as published by\n" \ + "the Free Software Foundation; either version 2 of the License, or\n" \ + "(at your option) any later version.\n" \ + "\n" \ + "This program is distributed in the hope that it will be useful,\n" \ + "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" \ + "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" \ + "GNU General Public License for more details.\n" \ + "\n" \ + "You should have received a copy of the GNU General Public License\n" \ + "along with this program; if not, write to the Free Software\n" \ + "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n"); + + gtk_dialog_run(GTK_DIALOG(about)); + gtk_widget_destroy(about); +} + +static void connect_to_wui (GtkWidget *widget, gpointer data) { const char *hostname; @@ -447,7 +496,7 @@ connect_to_vm (GtkWidget *widget, gpointer _vm) { struct vm *vm = (struct vm *) _vm; int n = gtk_notebook_get_n_pages (GTK_NOTEBOOK (notebook)); - int i, uuidlen, len; + int i, uuidlen, len, fd; GtkWidget *child; const char *label; char *label2; @@ -472,15 +521,48 @@ connect_to_vm (GtkWidget *widget, gpointer _vm) DEBUG ("not found, creating new tab"); /* This VM isn't in the notebook already, so create a new console. */ - len = strlen (vm->description) + 1 + strlen (vm->uuid) + 1; - label2 = g_alloca (len); - snprintf (label2, len, "%s %s", vm->description, vm->uuid); + fd = viewer_open_tunnel_ssh (/*vm->host XXX*/ "192.168.50.6", + 0, /* Default SSH port. */ + "root", /* Root account. */ + vm->vnc_port); + if (fd == -1) return; /* We've already given an error. */ + + child = vnc_display_new (); + if (! vnc_display_open_fd (VNC_DISPLAY (child), fd)) { + main_status_error (g_strdup ("internal error in Gtk-VNC widget")); + return; + } + + /* + gtk_signal_connect(GTK_OBJECT(child), "vnc-pointer-grab", + GTK_SIGNAL_FUNC(viewer_grab), window); + gtk_signal_connect(GTK_OBJECT(child), "vnc-pointer-ungrab", + GTK_SIGNAL_FUNC(viewer_ungrab), window); + */ - child = gtk_label_new (label2); /* XXX */ + gtk_signal_connect(GTK_OBJECT(child), "delete-event", + GTK_SIGNAL_FUNC(viewer_shutdown), child); + + gtk_signal_connect(GTK_OBJECT(child), "vnc-connected", + GTK_SIGNAL_FUNC(viewer_connected), NULL); + gtk_signal_connect(GTK_OBJECT(child), "vnc-initialized", + GTK_SIGNAL_FUNC(viewer_initialized), NULL); + gtk_signal_connect(GTK_OBJECT(child), "vnc-disconnected", + GTK_SIGNAL_FUNC(viewer_disconnected), NULL); + + g_signal_connect(GTK_OBJECT(child), "vnc-auth-credential", + GTK_SIGNAL_FUNC(viewer_credential), NULL); /* NB. We have to do this before adding it to the notebook. */ gtk_widget_show (child); + /* Choose a tab label, which MUST end with the uuid string, since + * we use the tab label to store uuid. + */ + len = strlen (vm->description) + 1 + strlen (vm->uuid) + 1; + label2 = g_alloca (len); + snprintf (label2, len, "%s %s", vm->description, vm->uuid); + i = gtk_notebook_append_page (GTK_NOTEBOOK (notebook), child, NULL); gtk_notebook_set_tab_label_text (GTK_NOTEBOOK (notebook), child, label2); gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), i); @@ -488,6 +570,237 @@ connect_to_vm (GtkWidget *widget, gpointer _vm) DEBUG ("finished creating new tab"); } +/* +static void viewer_grab(GtkWidget *vnc, GtkWidget *window) +{ + int i; + + viewer_set_title(VNC_DISPLAY(vnc), window, TRUE); + + for (i = 0 ; i < LAST_MENU; i++) { + gtk_label_set_text_with_mnemonic(GTK_LABEL(menuItems[i].label), menuItems[i].grabbed_text); + } +} + +static void viewer_ungrab(GtkWidget *vnc, GtkWidget *window) +{ + int i; + + viewer_set_title(VNC_DISPLAY(vnc), window, FALSE); + + for (i = 0 ; i < LAST_MENU; i++) { + gtk_label_set_text_with_mnemonic(GTK_LABEL(menuItems[i].label), menuItems[i].ungrabbed_text); + } +} +*/ + +static void +viewer_shutdown (GtkWidget *src, void *dummy, GtkWidget *vnc) +{ + vnc_display_close (VNC_DISPLAY(vnc)); + + /* Just close the notebook tab for now. XXX */ + gtk_notebook_remove_page (GTK_NOTEBOOK (notebook), + gtk_notebook_page_num (GTK_NOTEBOOK (notebook), + vnc)); +} + +static void +viewer_quit (GtkWidget *src, GtkWidget *vnc) +{ + viewer_shutdown (src, NULL, vnc); +} + +static void +viewer_connected (GtkWidget *vnc) +{ + DEBUG ("Connected to server"); +} + +static void +viewer_initialized (GtkWidget *vnc, GtkWidget *data) +{ + DEBUG ("Connection initialized"); +} + +static void +viewer_disconnected (GtkWidget *vnc) +{ + DEBUG ("Disconnected from server"); +} + +static void +viewer_credential (GtkWidget *vnc, GValueArray *credList) +{ + GtkWidget *dialog = NULL; + int response; + unsigned int i, prompt = 0; + const char **data; + + DEBUG ("Got credential request for %d credential(s)", + credList->n_values); + + data = g_new0(const char *, credList->n_values); + + for (i = 0 ; i < credList->n_values ; i++) { + GValue *cred = g_value_array_get_nth(credList, i); + switch (g_value_get_enum(cred)) { + case VNC_DISPLAY_CREDENTIAL_USERNAME: + case VNC_DISPLAY_CREDENTIAL_PASSWORD: + prompt++; + break; + case VNC_DISPLAY_CREDENTIAL_CLIENTNAME: + data[i] = "libvirt"; + default: + break; + } + } + + if (prompt) { + GtkWidget **label, **entry, *box, *vbox; + int row; + dialog = gtk_dialog_new_with_buttons("Authentication required", + NULL, + 0, + GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL, + GTK_STOCK_OK, + GTK_RESPONSE_OK, + NULL); + gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); + + box = gtk_table_new(credList->n_values, 2, FALSE); + label = g_new(GtkWidget *, prompt); + entry = g_new(GtkWidget *, prompt); + + for (i = 0, row =0 ; i < credList->n_values ; i++) { + GValue *cred = g_value_array_get_nth(credList, i); + switch (g_value_get_enum(cred)) { + case VNC_DISPLAY_CREDENTIAL_USERNAME: + label[row] = gtk_label_new("Username:"); + break; + case VNC_DISPLAY_CREDENTIAL_PASSWORD: + label[row] = gtk_label_new("Password:"); + break; + default: + continue; + } + entry[row] = gtk_entry_new(); + if (g_value_get_enum(cred) == VNC_DISPLAY_CREDENTIAL_PASSWORD) + gtk_entry_set_visibility(GTK_ENTRY(entry[row]), FALSE); + + gtk_table_attach(GTK_TABLE(box), label[i], 0, 1, row, row+1, GTK_SHRINK, GTK_SHRINK, 3, 3); + gtk_table_attach(GTK_TABLE(box), entry[i], 1, 2, row, row+1, GTK_SHRINK, GTK_SHRINK, 3, 3); + row++; + } + + vbox = gtk_bin_get_child(GTK_BIN(dialog)); + gtk_container_add(GTK_CONTAINER(vbox), box); + + gtk_widget_show_all(dialog); + response = gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_hide(GTK_WIDGET(dialog)); + + if (response == GTK_RESPONSE_OK) { + for (i = 0, row = 0 ; i < credList->n_values ; i++) { + GValue *cred = g_value_array_get_nth(credList, i); + switch (g_value_get_enum(cred)) { + case VNC_DISPLAY_CREDENTIAL_USERNAME: + case VNC_DISPLAY_CREDENTIAL_PASSWORD: + data[i] = gtk_entry_get_text(GTK_ENTRY(entry[row])); + break; + } + } + } + } + + for (i = 0 ; i < credList->n_values ; i++) { + GValue *cred = g_value_array_get_nth(credList, i); + if (data[i]) { + if (vnc_display_set_credential(VNC_DISPLAY(vnc), + g_value_get_enum(cred), + data[i])) { + DEBUG("Failed to set credential type %d", + g_value_get_enum(cred)); + vnc_display_close(VNC_DISPLAY(vnc)); + } + } else { + DEBUG("Unsupported credential type %d", + g_value_get_enum(cred)); + vnc_display_close(VNC_DISPLAY(vnc)); + } + } + + g_free(data); + if (dialog) + gtk_widget_destroy(GTK_WIDGET(dialog)); +} + +#if defined(HAVE_SOCKETPAIR) && defined(HAVE_FORK) + +static int viewer_open_tunnel(const char **cmd) +{ + int fd[2]; + pid_t pid; + + if (socketpair(PF_UNIX, SOCK_STREAM, 0, fd) < 0) + return -1; + + pid = fork(); + if (pid == -1) { + close(fd[0]); + close(fd[1]); + return -1; + } + + if (pid == 0) { /* child */ + close(fd[0]); + close(0); + close(1); + if (dup(fd[1]) < 0) + _exit(1); + if (dup(fd[1]) < 0) + _exit(1); + close(fd[1]); + execvp("ssh", (char *const*)cmd); + _exit(1); + } + close(fd[1]); + return fd[0]; +} + +static int +viewer_open_tunnel_ssh (const char *sshhost, int sshport, const char *sshuser, + int vncport) +{ + const char *cmd[10]; + char portstr[50], portstr2[50]; + int n = 0; + + if (!sshport) + sshport = 22; + + snprintf (portstr, sizeof portstr, "%d", sshport); + snprintf (portstr2, sizeof portstr2, "%d", vncport); + + cmd[n++] = "ssh"; + cmd[n++] = "-p"; + cmd[n++] = portstr; + if (sshuser) { + cmd[n++] = "-l"; + cmd[n++] = sshuser; + } + cmd[n++] = sshhost; + cmd[n++] = "nc"; + cmd[n++] = "localhost"; + cmd[n++] = portstr2; + cmd[n++] = NULL; + + return viewer_open_tunnel(cmd); +} + +#endif /* defined(HAVE_SOCKETPAIR) && defined(HAVE_FORK) */ + /* Remove all menu items from the Connect menu. */ static void remove_menu_item (GtkWidget *menu_item, gpointer data)