/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-â
âvi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :viâ
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ¡
â Copyright 2022 Justine Alexandra Roberts Tunney                              â
â                                                                              â
â Permission to use, copy, modify, and/or distribute this software for         â
â any purpose with or without fee is hereby granted, provided that the         â
â above copyright notice and this permission notice appear in all copies.      â
â                                                                              â
â THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                â
â WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                â
â WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             â
â AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         â
â DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        â
â PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               â
â TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             â
â PERFORMANCE OF THIS SOFTWARE.                                                â
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ*/
#include "libc/calls/calls.h"
#include "libc/calls/syscall_support-sysv.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/fmt/conv.h"
#include "libc/fmt/itoa.h"
#include "libc/intrin/kprintf.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/testlib/subprocess.h"
#include "libc/testlib/testlib.h"

#ifdef __x86_64__

#define N 16

char *GenBuf(char buf[8], int x) {
  int i;
  bzero(buf, 8);
  for (i = 0; i < 7; ++i) {
    buf[i] = x & 127;  // nt doesn't respect invalid unicode?
    x >>= 1;
  }
  return buf;
}

__attribute__((__constructor__)) static void init(void) {
  char buf[8];
  if (__argc == 4 && !strcmp(__argv[1], "-")) {
    ASSERT_STREQ(GenBuf(buf, atoi(__argv[2])), __argv[3]);
    exit(0);
  }
}

TEST(execve, testArgPassing) {
  int i;
  char ibuf[12], buf[8];
  for (i = 0; i < N; ++i) {
    FormatInt32(ibuf, i);
    GenBuf(buf, i);
    SPAWN(vfork);
    execve(GetProgramExecutableName(),
           (char *const[]){GetProgramExecutableName(), "-", ibuf, buf, 0},
           (char *const[]){0});
    kprintf("execve failed: %m\n");
    EXITS(0);
  }
}

TEST(execve, ziposELF) {
  if (IsFreebsd()) return;           // TODO: fixme on freebsd
  if (!__is_linux_2_6_23()) return;  // TODO: fixme on old linux
  if (!IsLinux() && !IsFreebsd()) {
    EXPECT_SYS(ENOSYS, -1,
               execve("/zip/life.elf", (char *const[]){0}, (char *const[]){0}));
    return;
  }
  SPAWN(fork);
  execve("/zip/life.elf", (char *const[]){0}, (char *const[]){0});
  kprintf("execve failed: %m\n");
  EXITS(42);
}

TEST(execve, ziposAPE) {
  if (IsFreebsd()) return;           // TODO: fixme on freebsd
  if (!__is_linux_2_6_23()) return;  // TODO: fixme on old linux
  if (!IsLinux() && !IsFreebsd()) {
    EXPECT_EQ(-1, execve("/zip/life-nomod.com", (char *const[]){0},
                         (char *const[]){0}));
    return;
  }
  SPAWN(fork);
  execve("/zip/life-nomod.com", (char *const[]){0}, (char *const[]){0});
  kprintf("execve failed: %m\n");
  EXITS(42);
}

#endif
