widget/xremoteclient/RemoteUtils.cpp
author L10n Bumper Bot <release+l10nbumper@mozilla.com>
Mon, 14 Jan 2019 04:00:15 -0800
changeset 506679 b6bde01c7a183e9191a23a005734b747d321620a
parent 505383 6f3709b3878117466168c40affa7bca0b60cf75b
child 511623 5f4630838d46dd81dadb13220a4af0da9e23a619
permissions -rw-r--r--
no bug - Bumping Fennec l10n changesets r=release a=l10n-bump DONTBUILD cak -> 3bd3d9938de2 ml -> da8508490cac trs -> a73bd0fa9499 uk -> de7742fa098e ur -> f3bfe0211b0d uz -> 6c42381becf7 vi -> 18fe987ca77d wo -> eaabeed6eb6c xh -> 1fe19625ce80 zam -> 5b7a669c784f zh-CN -> 2ff77a53b21c zh-TW -> 574f9f4100d8

/* -*- 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 <strings.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 *aDesktopStartupID,
                           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 desktopStartupPrefix[] = " DESKTOP_STARTUP_ID=";

  int32_t argvlen = strlen(cwdbuf);
  for (int i = 0; i < argc; ++i) {
    int32_t len = strlen(argv[i]);
    if (i == 0 && aDesktopStartupID) {
      len += sizeof(desktopStartupPrefix) - 1 + strlen(aDesktopStartupID);
    }
    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 && aDesktopStartupID) {
      bufend = estrcpy(desktopStartupPrefix, bufend - 1);
      bufend = estrcpy(aDesktopStartupID, 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);
}