summaryrefslogtreecommitdiffstats
path: root/toolkit/components/remote/RemoteUtils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/remote/RemoteUtils.cpp')
-rw-r--r--toolkit/components/remote/RemoteUtils.cpp102
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);
+}