/* * Copyright 2009-2017, Haiku, Inc. * Distributed under the terms of the MIT License. * * Authors: * Michael Lotz */ #include #include #include #include #include #include "RemoteView.h" #include #include #include #include #include #include void print_usage(const char *app) { printf("usage:\t%s [-p ] [-w ] [-h ]\n", app); printf("usage:\t%s -s [] [-p ] [-w ]" " [-h ] [-c ]\n", app); printf("\t%s --help\n\n", app); printf("Connect to & run applications from a different computer\n\n"); printf("Arguments available for use:\n\n"); printf("\t-p\t\tspecify the port to communicate on (default 10900)\n"); printf("\t-c\t\tsend a command to the other computer (default Terminal)\n"); printf("\t-s\t\tuse SSH, optionally specify the SSH port to use (22)\n"); printf("\t-w\t\tmake the virtual desktop use the specified width\n"); printf("\t-h\t\tmake the virtual desktop use the specified height\n"); printf("\nIf no width and height are specified, the window is opened with" " the size of the the local screen.\n"); } int main(int argc, char *argv[]) { if (argc < 2 || strcmp(argv[1], "--help") == 0) { print_usage(argv[0]); return 1; } uint16 port = 10900; uint16 sshPort = 22; int32 width = -1; int32 height = -1; bool useSSH = false; const char *command = NULL; const char *host = argv[1]; for (int32 i = 2; i < argc; i++) { if (strcmp(argv[i], "-p") == 0) { if (argc <= i + 1 || sscanf(argv[i + 1], "%" B_SCNu16, &port) != 1) { print_usage(argv[0]); return 2; } i++; continue; } if (strcmp(argv[i], "-w") == 0) { if (argc <= i + 1 || sscanf(argv[i + 1], "%" B_SCNd32, &width) != 1) { print_usage(argv[0]); return 2; } i++; continue; } if (strcmp(argv[i], "-h") == 0) { if (argc <= i + 1 || sscanf(argv[i + 1], "%" B_SCNd32, &height) != 1) { print_usage(argv[0]); return 2; } i++; continue; } if (strcmp(argv[i], "-s") == 0) { if (argc <= i + 1 || sscanf(argv[i + 1], "%" B_SCNu16, &sshPort) != 1) { print_usage(argv[0]); return 2; } i++; useSSH = true; continue; } if (strcmp(argv[i], "-c") == 0) { if (argc <= i + 1) { print_usage(argv[0]); return 2; } i++; command = argv[i]; continue; } print_usage(argv[0]); return 2; } if (command != NULL && !useSSH) { print_usage(argv[0]); return 2; } pid_t sshPID = -1; if (useSSH) { BPath terminalPath; if (command == NULL) { if (find_directory(B_SYSTEM_APPS_DIRECTORY, &terminalPath) != B_OK) { printf("failed to determine system-apps directory\n"); return 3; } if (terminalPath.Append("Terminal") != B_OK) { printf("failed to append to system-apps path\n"); return 3; } command = terminalPath.Path(); } char shellCommand[4096]; snprintf(shellCommand, sizeof(shellCommand), "echo connected; export TARGET_SCREEN=%" B_PRIu16 "; %s\n", port, command); int pipes[4]; if (pipe(&pipes[0]) != 0 || pipe(&pipes[2]) != 0) { printf("failed to create redirection pipes\n"); return 3; } sshPID = fork(); if (sshPID < 0) { printf("failed to fork ssh process\n"); return 3; } if (sshPID == 0) { // child code, redirect std* and execute ssh close(STDOUT_FILENO); close(STDIN_FILENO); dup2(pipes[1], STDOUT_FILENO); dup2(pipes[1], STDERR_FILENO); dup2(pipes[2], STDIN_FILENO); for (int32 i = 0; i < 4; i++) close(pipes[i]); char localRedirect[50]; sprintf(localRedirect, "localhost:%" B_PRIu16 ":localhost:%" B_PRIu16, port, port); char portNumber[10]; sprintf(portNumber, "%" B_PRIu16, sshPort); int result = execl("ssh", "-C", "-L", localRedirect, "-p", portNumber, "-o", "ExitOnForwardFailure=yes", host, shellCommand, NULL); // we don't get here unless there was an error in executing printf("failed to execute ssh process in child\n"); return result; } else { close(pipes[1]); close(pipes[2]); char buffer[10]; read(pipes[0], buffer, sizeof(buffer)); // block until connected/error message from ssh host = "localhost"; } } BApplication app("application/x-vnd.Haiku-RemoteDesktop"); BRect windowFrame = BRect(0, 0, width - 1, height - 1); if (!windowFrame.IsValid()) { BScreen screen; windowFrame = screen.Frame(); } BWindow *window = new(std::nothrow) BWindow(windowFrame, "RemoteDesktop", B_TITLED_WINDOW, B_QUIT_ON_WINDOW_CLOSE); if (window == NULL) { printf("no memory to allocate window\n"); return 4; } RemoteView *view = new(std::nothrow) RemoteView(window->Bounds(), host, port); if (view == NULL) { printf("no memory to allocate remote view\n"); return 4; } status_t init = view->InitCheck(); if (init != B_OK) { printf("initialization of remote view failed: %s\n", strerror(init)); delete view; return 5; } window->AddChild(view); view->MakeFocus(); window->Show(); app.Run(); if (sshPID >= 0) kill(sshPID, SIGHUP); return 0; }