// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <lib/processargs/processargs.h>
#include <zircon/syscalls.h>

// TODO(mcgrathr): Is there a better error code to use for marshalling
// protocol violations?
#define MALFORMED ZX_ERR_INVALID_ARGS

zx_status_t processargs_message_size(zx_handle_t channel, uint32_t* nbytes, uint32_t* nhandles) {
  zx_status_t status = _zx_channel_read(channel, 0, NULL, NULL, 0, 0, nbytes, nhandles);
  if (status == ZX_ERR_BUFFER_TOO_SMALL)
    status = ZX_OK;
  return status;
}

zx_status_t processargs_read(zx_handle_t bootstrap, void* buffer, uint32_t nbytes,
                             zx_handle_t handles[], uint32_t nhandles, zx_proc_args_t** pargs,
                             uint32_t** handle_info) {
  if (nbytes < sizeof(zx_proc_args_t))
    return ZX_ERR_INVALID_ARGS;
  if ((uintptr_t)buffer % alignof(zx_proc_args_t) != 0)
    return ZX_ERR_INVALID_ARGS;

  uint32_t got_bytes = 0;
  uint32_t got_handles = 0;
  zx_status_t status =
      _zx_channel_read(bootstrap, 0, buffer, handles, nbytes, nhandles, &got_bytes, &got_handles);
  if (status != ZX_OK)
    return status;
  if (got_bytes != nbytes || got_handles != nhandles)
    return ZX_ERR_INVALID_ARGS;

  zx_proc_args_t* const pa = buffer;

  if (pa->protocol != ZX_PROCARGS_PROTOCOL || pa->version != ZX_PROCARGS_VERSION)
    return MALFORMED;

  if (pa->handle_info_off < sizeof(*pa) || pa->handle_info_off % alignof(uint32_t) != 0 ||
      pa->handle_info_off > nbytes || (nbytes - pa->handle_info_off) / sizeof(uint32_t) < nhandles)
    return MALFORMED;

  if (pa->args_num > 0 && (pa->args_off < sizeof(*pa) || pa->args_off > nbytes ||
                           (nbytes - pa->args_off) < pa->args_num))
    return MALFORMED;

  if (pa->environ_num > 0 && (pa->environ_off < sizeof(*pa) || pa->environ_off > nbytes ||
                              (nbytes - pa->environ_off) < pa->environ_num))
    return MALFORMED;

  *pargs = pa;
  *handle_info = (void*)&((uint8_t*)buffer)[pa->handle_info_off];
  return ZX_OK;
}

void processargs_extract_handles(uint32_t nhandles, zx_handle_t handles[], uint32_t handle_info[],
                                 zx_handle_t* process_self, zx_handle_t* job_default,
                                 zx_handle_t* vmar_root_self, zx_handle_t* thread_self) {
  // Find the handles we're interested in among what we were given.
  for (uint32_t i = 0; i < nhandles; ++i) {
    switch (PA_HND_TYPE(handle_info[i])) {
      case PA_PROC_SELF:
        // The handle will have been installed already by dynamic
        // linker startup, but now we have another one.  They
        // should of course be handles to the same process, but
        // just for cleanliness switch to the "main" one.
        if (*process_self != ZX_HANDLE_INVALID)
          _zx_handle_close(*process_self);
        *process_self = handles[i];
        handles[i] = ZX_HANDLE_INVALID;
        handle_info[i] = 0;
        break;

      case PA_JOB_DEFAULT:
        // The default job provided to the process to use for
        // creation of additional processes.  It may or may not
        // be the job this process is a child of.  It may not
        // be provided at all.
        if (*job_default != ZX_HANDLE_INVALID)
          _zx_handle_close(*job_default);
        *job_default = handles[i];
        handles[i] = ZX_HANDLE_INVALID;
        handle_info[i] = 0;
        break;

      case PA_VMAR_ROOT:
        // As above for PROC_SELF
        if (*vmar_root_self != ZX_HANDLE_INVALID)
          _zx_handle_close(*vmar_root_self);
        *vmar_root_self = handles[i];
        handles[i] = ZX_HANDLE_INVALID;
        handle_info[i] = 0;
        break;

      case PA_THREAD_SELF:
        *thread_self = handles[i];
        handles[i] = ZX_HANDLE_INVALID;
        handle_info[i] = 0;
        break;
    }
  }
}

static zx_status_t unpack_strings(char* buffer, uint32_t bytes, char* result[], uint32_t off,
                                  uint32_t num) {
  char* p = &buffer[off];
  for (uint32_t i = 0; i < num; ++i) {
    result[i] = p;
    do {
      if (p >= &buffer[bytes])
        return MALFORMED;
    } while (*p++ != '\0');
  }
  result[num] = NULL;
  return ZX_OK;
}

zx_status_t processargs_strings(void* msg, uint32_t bytes, char* argv[], char* envp[],
                                char* names[]) {
  zx_proc_args_t* const pa = msg;
  zx_status_t status = ZX_OK;
  if (argv != NULL) {
    status = unpack_strings(msg, bytes, argv, pa->args_off, pa->args_num);
  }
  if (envp != NULL && status == ZX_OK) {
    status = unpack_strings(msg, bytes, envp, pa->environ_off, pa->environ_num);
  }
  if (names != NULL && status == ZX_OK) {
    status = unpack_strings(msg, bytes, names, pa->names_off, pa->names_num);
  }
  return status;
}
