/*
 * Copyright 2021 Collabora Ltd.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, see
 * <http://www.gnu.org/licenses/>.
 */

#include <errno.h>
#include <stdio.h>

#include <glib.h>

#ifdef G_OS_UNIX
#include <sys/types.h>
#include <sys/wait.h>
#endif

static void
child_setup (gpointer user_data)
{
}

typedef struct
{
  int wait_status;
  gboolean done;
} ChildStatus;

static ChildStatus child_status = { -1, FALSE };

static void
child_watch_cb (GPid pid,
                gint status,
                gpointer user_data)
{
  child_status.wait_status = status;
  child_status.done = TRUE;
}

int
main (int    argc,
      char **argv)
{
  gboolean search_path = FALSE;
  gboolean search_path_from_envp = FALSE;
  gboolean slow_path = FALSE;
  gboolean unset_path_in_envp = FALSE;
  gchar *chdir_child = NULL;
  gchar *set_path_in_envp = NULL;
  gchar **envp = NULL;
  GOptionEntry entries[] =
  {
    { "chdir-child", '\0',
      G_OPTION_FLAG_NONE, G_OPTION_ARG_FILENAME, &chdir_child,
      "Run PROGRAM in this working directory", NULL },
    { "search-path", '\0',
      G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &search_path,
      "Search PATH for PROGRAM", NULL },
    { "search-path-from-envp", '\0',
      G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &search_path_from_envp,
      "Search PATH from specified environment", NULL },
    { "set-path-in-envp", '\0',
      G_OPTION_FLAG_NONE, G_OPTION_ARG_FILENAME, &set_path_in_envp,
      "Set PATH in specified environment to this value", "PATH", },
    { "unset-path-in-envp", '\0',
      G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &unset_path_in_envp,
      "Unset PATH in specified environment", NULL },
    { "slow-path", '\0',
      G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &slow_path,
      "Use a child-setup function to avoid the posix_spawn fast path", NULL },
    G_OPTION_ENTRY_NULL
  };
  GError *error = NULL;
  int ret = 1;
  GSpawnFlags spawn_flags = G_SPAWN_DO_NOT_REAP_CHILD;
  GPid pid;
  GOptionContext *context = NULL;

  context = g_option_context_new ("PROGRAM [ARGS...]");
  g_option_context_add_main_entries (context, entries, NULL);

  if (!g_option_context_parse (context, &argc, &argv, &error))
    {
      ret = 2;
      goto out;
    }

  if (argc < 2)
    {
      g_set_error (&error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED,
                   "Usage: %s [OPTIONS] PROGRAM [ARGS...]", argv[0]);
      ret = 2;
      goto out;
    }

  envp = g_get_environ ();

  if (set_path_in_envp != NULL && unset_path_in_envp)
    {
      g_set_error (&error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED,
                   "Cannot both set PATH and unset it");
      ret = 2;
      goto out;
    }

  if (set_path_in_envp != NULL)
    envp = g_environ_setenv (envp, "PATH", set_path_in_envp, TRUE);

  if (unset_path_in_envp)
    envp = g_environ_unsetenv (envp, "PATH");

  if (search_path)
    spawn_flags |= G_SPAWN_SEARCH_PATH;

  if (search_path_from_envp)
    spawn_flags |= G_SPAWN_SEARCH_PATH_FROM_ENVP;

  if (!g_spawn_async_with_pipes (chdir_child,
                                 &argv[1],
                                 envp,
                                 spawn_flags,
                                 slow_path ? child_setup : NULL,
                                 NULL,  /* user_data */
                                 &pid,
                                 NULL,  /* stdin */
                                 NULL,  /* stdout */
                                 NULL,  /* stderr */
                                 &error))
    {
      ret = 1;
      goto out;
    }

  g_child_watch_add (pid, child_watch_cb, NULL);

  while (!child_status.done)
    g_main_context_iteration (NULL, TRUE);

  g_spawn_close_pid (pid);

#ifdef G_OS_UNIX
  if (WIFEXITED (child_status.wait_status))
    ret = WEXITSTATUS (child_status.wait_status);
  else
    ret = 1;
#else
  ret = child_status.wait_status;
#endif

out:
  if (error != NULL)
    fprintf (stderr, "%s\n", error->message);

  g_free (set_path_in_envp);
  g_free (chdir_child);
  g_clear_error (&error);
  g_strfreev (envp);
  g_option_context_free (context);
  return ret;
}
