1 /* 2 * Copyright 2009, Haiku, Inc. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Michael Lotz <mmlr@mlotz.ch> 7 */ 8 9 #include <Application.h> 10 #include <Screen.h> 11 #include <Window.h> 12 13 #include "RemoteView.h" 14 15 #include <new> 16 #include <signal.h> 17 #include <stdio.h> 18 #include <string.h> 19 #include <sys/wait.h> 20 #include <unistd.h> 21 22 23 void 24 print_usage(const char *app) 25 { 26 printf("usage:\t%s --listenOnly [-p <listenPort>]\n", app); 27 printf("\t%s <user@host> [-p <listenPort>] [-s <sshPort>] [-c <command>]\n", 28 app); 29 } 30 31 32 int 33 main(int argc, char *argv[]) 34 { 35 if (argc < 2) { 36 print_usage(argv[0]); 37 return 1; 38 } 39 40 bool listenOnly = false; 41 uint32 listenPort = 10900; 42 uint32 sshPort = 22; 43 const char *command = "/system/apps/Terminal"; 44 45 for (int32 i = 2; i < argc; i++) { 46 if (strcmp(argv[i], "-p") == 0) { 47 if (argc < i + 1 || sscanf(argv[i + 1], "%lu", &listenPort) != 1) { 48 print_usage(argv[0]); 49 return 2; 50 } 51 52 i++; 53 continue; 54 } 55 56 if (strcmp(argv[i], "-s") == 0) { 57 if (argc < i + 1 || sscanf(argv[i + 1], "%lu", &sshPort) != 1) { 58 print_usage(argv[0]); 59 return 2; 60 } 61 62 i++; 63 continue; 64 } 65 66 if (strcmp(argv[i], "-c") == 0) { 67 if (argc < i + 1) { 68 print_usage(argv[0]); 69 return 2; 70 } 71 72 i++; 73 command = argv[i]; 74 continue; 75 } 76 77 if (strcmp(argv[i], "--listenOnly") == 0) { 78 listenOnly = true; 79 continue; 80 } 81 82 print_usage(argv[0]); 83 return 2; 84 } 85 86 pid_t sshPID = -1; 87 if (!listenOnly) { 88 char shellCommand[4096]; 89 snprintf(shellCommand, sizeof(shellCommand), 90 "echo connected; export TARGET_SCREEN=localhost:%lu; %s\n", 91 listenPort, command); 92 93 int pipes[4]; 94 if (pipe(&pipes[0]) != 0 || pipe(&pipes[2]) != 0) { 95 printf("failed to create redirection pipes\n"); 96 return 3; 97 } 98 99 sshPID = fork(); 100 if (sshPID < 0) { 101 printf("failed to fork ssh process\n"); 102 return 3; 103 } 104 105 if (sshPID == 0) { 106 // child code, redirect std* and execute ssh 107 close(STDOUT_FILENO); 108 close(STDIN_FILENO); 109 dup2(pipes[1], STDOUT_FILENO); 110 dup2(pipes[1], STDERR_FILENO); 111 dup2(pipes[2], STDIN_FILENO); 112 for (int32 i = 0; i < 4; i++) 113 close(pipes[i]); 114 115 char localRedirect[50]; 116 sprintf(localRedirect, "localhost:%lu:localhost:%lu", 117 listenPort + 1, listenPort + 1); 118 119 char remoteRedirect[50]; 120 sprintf(remoteRedirect, "localhost:%lu:localhost:%lu", 121 listenPort, listenPort); 122 123 char portNumber[10]; 124 sprintf(portNumber, "%lu", sshPort); 125 126 int result = execl("ssh", "-C", "-L", localRedirect, 127 "-R", remoteRedirect, "-p", portNumber, argv[1], 128 shellCommand, NULL); 129 130 // we don't get here unless there was an error in executing 131 printf("failed to execute ssh process in child\n"); 132 return result; 133 } else { 134 close(pipes[1]); 135 close(pipes[2]); 136 137 char buffer[10]; 138 read(pipes[0], buffer, sizeof(buffer)); 139 // block until connected/error message from ssh 140 } 141 } 142 143 BApplication app("application/x-vnd.Haiku-RemoteDesktop"); 144 BScreen screen; 145 BWindow *window = new(std::nothrow) BWindow(screen.Frame(), "RemoteDesktop", 146 B_TITLED_WINDOW, B_QUIT_ON_WINDOW_CLOSE); 147 148 if (window == NULL) { 149 printf("no memory to allocate window\n"); 150 return 4; 151 } 152 153 RemoteView *view = new(std::nothrow) RemoteView(window->Bounds(), 154 listenPort); 155 if (view == NULL) { 156 printf("no memory to allocate remote view\n"); 157 return 4; 158 } 159 160 status_t init = view->InitCheck(); 161 if (init != B_OK) { 162 printf("initialization of remote view failed: %s\n", strerror(init)); 163 delete view; 164 return 5; 165 } 166 167 window->AddChild(view); 168 view->MakeFocus(); 169 window->Show(); 170 app.Run(); 171 172 if (sshPID >= 0) 173 kill(sshPID, SIGINT); 174 175 return 0; 176 } 177