Bug 1943650 - Command-line --help output misformatted after --dbus-service. r=emilio
[gecko.git] / toolkit / components / remote / RemoteUtils.cpp
blob4f0ad838488da930a3bbd79bab775a3d5c0865df
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:expandtab:shiftwidth=2:tabstop=8:
3 */
4 /* vim:set ts=8 sw=2 et cindent: */
5 /* This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
9 #include <stdlib.h>
10 #include <string.h>
11 #include <unistd.h>
12 #include <limits.h>
14 #include "RemoteUtils.h"
16 #ifdef IS_BIG_ENDIAN
17 # define TO_LITTLE_ENDIAN32(x) \
18 ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
19 (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
20 #else
21 # define TO_LITTLE_ENDIAN32(x) (x)
22 #endif
24 #ifndef MAX_PATH
25 # ifdef PATH_MAX
26 # define MAX_PATH PATH_MAX
27 # else
28 # define MAX_PATH 1024
29 # endif
30 #endif
32 /* like strcpy, but return the char after the final null */
33 static char* estrcpy(const char* s, char* d) {
34 while (*s) *d++ = *s++;
36 *d++ = '\0';
37 return d;
40 /* Construct a command line from given args and desktop startup ID.
41 * Returned buffer must be released by free().
43 char* ConstructCommandLine(int32_t argc, const char** argv,
44 const char* aStartupToken, int* aCommandLineLength) {
45 char cwdbuf[MAX_PATH];
46 if (!getcwd(cwdbuf, MAX_PATH)) return nullptr;
48 // the commandline property is constructed as an array of int32_t
49 // followed by a series of null-terminated strings:
51 // [argc][offsetargv0][offsetargv1...]<workingdir>\0<argv[0]>\0argv[1]...\0
52 // (offset is from the beginning of the buffer)
54 static char startupTokenPrefix[] = " STARTUP_TOKEN=";
56 int32_t argvlen = strlen(cwdbuf);
57 for (int i = 0; i < argc; ++i) {
58 int32_t len = strlen(argv[i]);
59 if (i == 0 && aStartupToken) {
60 len += sizeof(startupTokenPrefix) - 1 + strlen(aStartupToken);
62 argvlen += len;
65 auto* buffer =
66 (int32_t*)malloc(argvlen + argc + 1 + sizeof(int32_t) * (argc + 1));
67 if (!buffer) return nullptr;
69 buffer[0] = TO_LITTLE_ENDIAN32(argc);
71 auto* bufend = (char*)(buffer + argc + 1);
73 bufend = estrcpy(cwdbuf, bufend);
75 for (int i = 0; i < argc; ++i) {
76 buffer[i + 1] = TO_LITTLE_ENDIAN32(bufend - ((char*)buffer));
77 bufend = estrcpy(argv[i], bufend);
78 if (i == 0 && aStartupToken) {
79 bufend = estrcpy(startupTokenPrefix, bufend - 1);
80 bufend = estrcpy(aStartupToken, bufend - 1);
84 #ifdef DEBUG_command_line
85 int32_t debug_argc = TO_LITTLE_ENDIAN32(*buffer);
86 char* debug_workingdir = (char*)(buffer + argc + 1);
88 printf(
89 "Sending command line:\n"
90 " working dir: %s\n"
91 " argc:\t%i",
92 debug_workingdir, debug_argc);
94 int32_t* debug_offset = buffer + 1;
95 for (int debug_i = 0; debug_i < debug_argc; ++debug_i)
96 printf(" argv[%i]:\t%s\n", debug_i,
97 ((char*)buffer) + TO_LITTLE_ENDIAN32(debug_offset[debug_i]));
98 #endif
100 *aCommandLineLength = bufend - reinterpret_cast<char*>(buffer);
101 return reinterpret_cast<char*>(buffer);