1/* $Id$ */ 2 3/*** 4 This file is part of avahi. 5 6 avahi is free software; you can redistribute it and/or modify it 7 under the terms of the GNU Lesser General Public License as 8 published by the Free Software Foundation; either version 2.1 of the 9 License, or (at your option) any later version. 10 11 avahi is distributed in the hope that it will be useful, but WITHOUT 12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General 14 Public License for more details. 15 16 You should have received a copy of the GNU Lesser General Public 17 License along with avahi; if not, write to the Free Software 18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 19 USA. 20***/ 21 22#ifdef HAVE_CONFIG_H 23#include <config.h> 24#endif 25 26#include <string.h> 27#include <unistd.h> 28#include <errno.h> 29#include <stdlib.h> 30#include <locale.h> 31#include <getopt.h> 32 33#include <gtk/gtk.h> 34#include <glib/gi18n.h> 35 36#include <avahi-client/client.h> 37#include <avahi-common/strlst.h> 38#include <avahi-common/malloc.h> 39#include <avahi-common/domain.h> 40#include <avahi-common/i18n.h> 41 42#include "avahi-ui.h" 43 44typedef enum { 45 COMMAND_HELP, 46 COMMAND_SSH, 47 COMMAND_VNC, 48 COMMAND_SHELL 49} Command; 50 51typedef struct Config { 52 char *domain; 53 Command command; 54} Config; 55 56static void help(FILE *f, const char *argv0) { 57 fprintf(f, 58 _("%s [options]\n\n" 59 " -h --help Show this help\n" 60 " -s --ssh Browse SSH servers\n" 61 " -v --vnc Browse VNC servers\n" 62 " -S --shell Browse both SSH and VNC\n" 63 " -d --domain=DOMAIN The domain to browse in\n"), 64 argv0); 65} 66 67static int parse_command_line(Config *c, int argc, char *argv[]) { 68 int o; 69 70 static const struct option long_options[] = { 71 { "help", no_argument, NULL, 'h' }, 72 { "ssh", no_argument, NULL, 's' }, 73 { "vnc", no_argument, NULL, 'v' }, 74 { "shell", no_argument, NULL, 'S' }, 75 { "domain", required_argument, NULL, 'd' }, 76 { NULL, 0, NULL, 0 } 77 }; 78 79 while ((o = getopt_long(argc, argv, "hVd:svS", long_options, NULL)) >= 0) { 80 81 switch(o) { 82 case 'h': 83 c->command = COMMAND_HELP; 84 break; 85 case 's': 86 c->command = COMMAND_SSH; 87 break; 88 case 'v': 89 c->command = COMMAND_VNC; 90 break; 91 case 'S': 92 c->command = COMMAND_SHELL; 93 break; 94 case 'd': 95 avahi_free(c->domain); 96 c->domain = avahi_strdup(optarg); 97 break; 98 default: 99 return -1; 100 } 101 } 102 103 if (optind < argc) { 104 fprintf(stderr, _("Too many arguments\n")); 105 return -1; 106 } 107 108 return 0; 109} 110 111int main(int argc, char*argv[]) { 112 GtkWidget *d; 113 Config config; 114 const char *argv0; 115 116 avahi_init_i18n(); 117 setlocale(LC_ALL, ""); 118 119 if ((argv0 = strrchr(argv[0], '/'))) 120 argv0++; 121 else 122 argv0 = argv[0]; 123 124 if (g_str_has_suffix(argv[0], "bshell")) 125 config.command = COMMAND_SHELL; 126 else if (g_str_has_suffix(argv[0], "bvnc")) 127 config.command = COMMAND_VNC; 128 else 129 config.command = COMMAND_SSH; 130 131 /* defaults to local */ 132 config.domain = NULL; 133 134 if (parse_command_line(&config, argc, argv) < 0) { 135 help(stderr, argv0); 136 return 1; 137 } 138 139 bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); 140 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); 141 textdomain (GETTEXT_PACKAGE); 142 143 gtk_init(&argc, &argv); 144 145 switch (config.command) { 146 case COMMAND_HELP: 147 help(stdout, argv0); 148 return 0; 149 break; 150 151 case COMMAND_SHELL: 152 d = aui_service_dialog_new(_("Choose Shell Server"), NULL, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_CONNECT, GTK_RESPONSE_ACCEPT, NULL); 153 aui_service_dialog_set_browse_service_types(AUI_SERVICE_DIALOG(d), "_rfb._tcp", "_ssh._tcp", NULL); 154 aui_service_dialog_set_service_type_name(AUI_SERVICE_DIALOG(d), "_rfb._tcp", _("Desktop")); 155 aui_service_dialog_set_service_type_name(AUI_SERVICE_DIALOG(d), "_ssh._tcp", _("Terminal")); 156 break; 157 158 case COMMAND_VNC: 159 d = aui_service_dialog_new(_("Choose VNC server"), NULL, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_CONNECT, GTK_RESPONSE_ACCEPT, NULL); 160 aui_service_dialog_set_browse_service_types(AUI_SERVICE_DIALOG(d), "_rfb._tcp", NULL); 161 break; 162 163 case COMMAND_SSH: 164 d = aui_service_dialog_new(_("Choose SSH server"), NULL, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_CONNECT, GTK_RESPONSE_ACCEPT, NULL); 165 aui_service_dialog_set_browse_service_types(AUI_SERVICE_DIALOG(d), "_ssh._tcp", NULL); 166 break; 167 } 168 169 aui_service_dialog_set_domain (AUI_SERVICE_DIALOG(d), config.domain); 170 aui_service_dialog_set_resolve_service(AUI_SERVICE_DIALOG(d), TRUE); 171 aui_service_dialog_set_resolve_host_name(AUI_SERVICE_DIALOG(d), !avahi_nss_support()); 172 173 gtk_window_present(GTK_WINDOW(d)); 174 175 if (gtk_dialog_run(GTK_DIALOG(d)) == GTK_RESPONSE_ACCEPT) { 176 char a[AVAHI_ADDRESS_STR_MAX], *u = NULL, *n = NULL; 177 char *h = NULL, *t = NULL; 178 const AvahiStringList *txt; 179 180 t = g_strdup(aui_service_dialog_get_service_type(AUI_SERVICE_DIALOG(d))); 181 n = g_strdup(aui_service_dialog_get_service_name(AUI_SERVICE_DIALOG(d))); 182 183 if (avahi_nss_support()) 184 h = g_strdup(aui_service_dialog_get_host_name(AUI_SERVICE_DIALOG(d))); 185 else 186 h = g_strdup(avahi_address_snprint(a, sizeof(a), aui_service_dialog_get_address(AUI_SERVICE_DIALOG(d)))); 187 188 g_print(_("Connecting to '%s' ...\n"), n); 189 190 if (avahi_domain_equal(t, "_rfb._tcp")) { 191 char p[AVAHI_DOMAIN_NAME_MAX+16]; 192 snprintf(p, sizeof(p), "%s:%u", h, aui_service_dialog_get_port(AUI_SERVICE_DIALOG(d))-5900); 193 194 gtk_widget_destroy(d); 195 196 g_print("vncviewer %s\n", p); 197 execlp("xvncviewer", "xvncviewer", p, NULL); 198 execlp("vncviewer", "vncviewer", p, NULL); 199 200 } else { 201 char p[16]; 202 203 snprintf(p, sizeof(p), "%u", aui_service_dialog_get_port(AUI_SERVICE_DIALOG(d))); 204 205 for (txt = aui_service_dialog_get_txt_data(AUI_SERVICE_DIALOG(d)); txt; txt = txt->next) { 206 char *key, *value; 207 208 if (avahi_string_list_get_pair((AvahiStringList*) txt, &key, &value, NULL) < 0) 209 break; 210 211 if (strcmp(key, "u") == 0) 212 u = g_strdup(value); 213 214 avahi_free(key); 215 avahi_free(value); 216 } 217 218 gtk_widget_destroy(d); 219 220 if (u) { 221 g_print("ssh -p %s -l %s %s\n", p, u, h); 222 223 if (isatty(0) || !getenv("DISPLAY")) 224 execlp("ssh", "ssh", "-p", p, "-l", u, h, NULL); 225 else { 226 execlp("x-terminal-emulator", "x-terminal-emulator", "-T", n, "-e", "ssh", "-p", p, "-l", u, h, NULL); 227 execlp("gnome-terminal", "gnome-terminal", "-t", n, "-x", "ssh", "-p", p, "-l", u, h, NULL); 228 execlp("xterm", "xterm", "-T", n, "-e", "ssh", "-p", p, "-l", u, h, NULL); 229 } 230 } else { 231 g_print("ssh -p %s %s\n", p, h); 232 233 if (isatty(0) || !getenv("DISPLAY")) 234 execlp("ssh", "ssh", "-p", p, h, NULL); 235 else { 236 execlp("x-terminal-emulator", "x-terminal-emulator", "-T", n, "-e", "ssh", "-p", p, h, NULL); 237 execlp("gnome-terminal", "gnome-terminal", "-t", n, "-x", "ssh", "-p", p, h, NULL); 238 execlp("xterm", "xterm", "-T", n, "-e", "ssh", "-p", p, h, NULL); 239 } 240 } 241 } 242 243 g_warning(_("execlp() failed: %s\n"), strerror(errno)); 244 245 g_free(h); 246 g_free(u); 247 g_free(t); 248 g_free(n); 249 250 } else { 251 gtk_widget_destroy(d); 252 253 g_print(_("Canceled.\n")); 254 } 255 256 g_free(config.domain); 257 258 return 1; 259} 260