diff options
Diffstat (limited to 'toolkit/components/remote/RemoteUtils.cpp')
-rw-r--r-- | toolkit/components/remote/RemoteUtils.cpp | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/toolkit/components/remote/RemoteUtils.cpp b/toolkit/components/remote/RemoteUtils.cpp new file mode 100644 index 0000000000..f7677f92b9 --- /dev/null +++ b/toolkit/components/remote/RemoteUtils.cpp @@ -0,0 +1,102 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:expandtab:shiftwidth=2:tabstop=8: + */ +/* vim:set ts=8 sw=2 et cindent: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <limits.h> + +#include "RemoteUtils.h" + +#ifdef IS_BIG_ENDIAN +# define TO_LITTLE_ENDIAN32(x) \ + ((((x)&0xff000000) >> 24) | (((x)&0x00ff0000) >> 8) | \ + (((x)&0x0000ff00) << 8) | (((x)&0x000000ff) << 24)) +#else +# define TO_LITTLE_ENDIAN32(x) (x) +#endif + +#ifndef MAX_PATH +# ifdef PATH_MAX +# define MAX_PATH PATH_MAX +# else +# define MAX_PATH 1024 +# endif +#endif + +/* like strcpy, but return the char after the final null */ +static char* estrcpy(const char* s, char* d) { + while (*s) *d++ = *s++; + + *d++ = '\0'; + return d; +} + +/* Construct a command line from given args and desktop startup ID. + * Returned buffer must be released by free(). + */ +char* ConstructCommandLine(int32_t argc, char** argv, const char* aStartupToken, + int* aCommandLineLength) { + char cwdbuf[MAX_PATH]; + if (!getcwd(cwdbuf, MAX_PATH)) return nullptr; + + // the commandline property is constructed as an array of int32_t + // followed by a series of null-terminated strings: + // + // [argc][offsetargv0][offsetargv1...]<workingdir>\0<argv[0]>\0argv[1]...\0 + // (offset is from the beginning of the buffer) + + static char startupTokenPrefix[] = " STARTUP_TOKEN="; + + int32_t argvlen = strlen(cwdbuf); + for (int i = 0; i < argc; ++i) { + int32_t len = strlen(argv[i]); + if (i == 0 && aStartupToken) { + len += sizeof(startupTokenPrefix) - 1 + strlen(aStartupToken); + } + argvlen += len; + } + + auto* buffer = + (int32_t*)malloc(argvlen + argc + 1 + sizeof(int32_t) * (argc + 1)); + if (!buffer) return nullptr; + + buffer[0] = TO_LITTLE_ENDIAN32(argc); + + auto* bufend = (char*)(buffer + argc + 1); + + bufend = estrcpy(cwdbuf, bufend); + + for (int i = 0; i < argc; ++i) { + buffer[i + 1] = TO_LITTLE_ENDIAN32(bufend - ((char*)buffer)); + bufend = estrcpy(argv[i], bufend); + if (i == 0 && aStartupToken) { + bufend = estrcpy(startupTokenPrefix, bufend - 1); + bufend = estrcpy(aStartupToken, bufend - 1); + } + } + +#ifdef DEBUG_command_line + int32_t debug_argc = TO_LITTLE_ENDIAN32(*buffer); + char* debug_workingdir = (char*)(buffer + argc + 1); + + printf( + "Sending command line:\n" + " working dir: %s\n" + " argc:\t%i", + debug_workingdir, debug_argc); + + int32_t* debug_offset = buffer + 1; + for (int debug_i = 0; debug_i < debug_argc; ++debug_i) + printf(" argv[%i]:\t%s\n", debug_i, + ((char*)buffer) + TO_LITTLE_ENDIAN32(debug_offset[debug_i])); +#endif + + *aCommandLineLength = bufend - reinterpret_cast<char*>(buffer); + return reinterpret_cast<char*>(buffer); +} |