From 8bca7393153ce120c74128d0345daabe7ad000ec Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 3 Nov 2011 16:25:35 -0400 Subject: [PATCH] Some work on ostree-build --- Makefile-osbuild.am | 38 ++++++ Makefile-ostree.am | 2 +- Makefile-otutil.am | 2 + Makefile.am | 1 + libotutil/ot-glib-compat.c | 159 +++++++++++++++++++++++++ libotutil/ot-glib-compat.h | 52 ++++++++ libotutil/ot-opt-utils.h | 4 +- libotutil/ot-unix-utils.c | 16 +++ libotutil/ot-unix-utils.h | 4 + libotutil/otutil.h | 1 + osbuild/main.c | 107 +++++++++++++++++ osbuild/ob-builtin-buildone.c | 134 +++++++++++++++++++++ osbuild/ob-builtins.h | 43 +++++++ osbuild/osbuild-raw-makeinstall.c | 189 ++++++++++++++++++++++++++++++ 14 files changed, 749 insertions(+), 3 deletions(-) create mode 100644 Makefile-osbuild.am create mode 100644 libotutil/ot-glib-compat.c create mode 100644 libotutil/ot-glib-compat.h create mode 100644 osbuild/main.c create mode 100644 osbuild/ob-builtin-buildone.c create mode 100644 osbuild/ob-builtins.h create mode 100644 osbuild/osbuild-raw-makeinstall.c diff --git a/Makefile-osbuild.am b/Makefile-osbuild.am new file mode 100644 index 00000000..9373fdf9 --- /dev/null +++ b/Makefile-osbuild.am @@ -0,0 +1,38 @@ +# Makefile for C source code +# +# Copyright (C) 2011 Colin Walters +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# Author: Colin Walters + +bin_PROGRAMS += ostree-build + +osbuild_common_cflags = -I$(srcdir)/libotutil -I$(srcdir)/osbuild -DLOCALEDIR=\"$(datadir)/locale\" -DG_LOG_DOMAIN=\"osbuild\" $(GIO_UNIX_CFLAGS) +osbuild_common_ldadd = libotutil.la $(GIO_UNIX_LIBS) + +ostree_build_SOURCES = osbuild/main.c \ + osbuild/ob-builtins.h \ + osbuild/ob-builtin-buildone.c \ + $(NULL) +ostree_build_CFLAGS = $(osbuild_common_cflags) +ostree_build_LDADD = $(osbuild_common_ldadd) + +bin_PROGRAMS += osbuild-raw-makeinstall + +osbuild_raw_makeinstall_SOURCES = osbuild/osbuild-raw-makeinstall.c \ + $(NULL) +osbuild_raw_makeinstall_CFLAGS = $(osbuild_common_cflags) +osbuild_raw_makeinstall_LDADD = $(osbuild_common_ldadd) diff --git a/Makefile-ostree.am b/Makefile-ostree.am index 01ffbecc..ef26c81f 100644 --- a/Makefile-ostree.am +++ b/Makefile-ostree.am @@ -34,5 +34,5 @@ ostree_SOURCES = ostree/main.c \ ostree/ot-builtin-rev-parse.c \ ostree/ot-builtin-show.c \ $(NULL) -ostree_CFLAGS = -I$(srcdir)/src -I$(srcdir)/libostree -I$(srcdir)/libotutil -DLOCALEDIR=\"$(datadir)/locale\" $(OT_COREBIN_DEP_CFLAGS) +ostree_CFLAGS = -I$(srcdir)/libotutil -I$(srcdir)/libostree -I$(srcdir)/ostree -DLOCALEDIR=\"$(datadir)/locale\" $(OT_COREBIN_DEP_CFLAGS) ostree_LDADD = libotutil.la libostree.la $(OT_COREBIN_DEP_LIBS) diff --git a/Makefile-otutil.am b/Makefile-otutil.am index 8df7c5b4..2e492b89 100644 --- a/Makefile-otutil.am +++ b/Makefile-otutil.am @@ -27,6 +27,8 @@ libotutil_la_SOURCES = \ libotutil/ot-unix-utils.h \ libotutil/ot-gio-utils.c \ libotutil/ot-gio-utils.h \ + libotutil/ot-glib-compat.c \ + libotutil/ot-glib-compat.h \ libotutil/otutil.h \ $(NULL) libotutil_la_CFLAGS = -I$(srcdir)/libotutil -DLOCALEDIR=\"$(datadir)/locale\" $(GIO_UNIX_CFLAGS) diff --git a/Makefile.am b/Makefile.am index 3dbda721..2404075d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -14,4 +14,5 @@ noinst_PROGRAMS = include Makefile-otutil.am include Makefile-libostree.am include Makefile-ostree.am +include Makefile-osbuild.am include Makefile-triggers.am diff --git a/libotutil/ot-glib-compat.c b/libotutil/ot-glib-compat.c new file mode 100644 index 00000000..16d4cf54 --- /dev/null +++ b/libotutil/ot-glib-compat.c @@ -0,0 +1,159 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2011 Colin Walters + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Author: Colin Walters + */ + +#include "config.h" + +#include + +#include + +#include "otutil.h" + +#if GLIB_CHECK_VERSION(2,32,0) +/* nothing */ +#else +/* Code copied from glib/glib/genviron.c */ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1998 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * 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 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, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +static gint +ot_g_environ_find (gchar **envp, + const gchar *variable) +{ + gint len, i; + + len = strlen (variable); + + for (i = 0; envp[i]; i++) + { + if (strncmp (envp[i], variable, len) == 0 && + envp[i][len] == '=') + return i; + } + + return -1; +} + +const gchar * +ot_g_environ_getenv (gchar **envp, + const gchar *variable) +{ + gint index; + + g_return_val_if_fail (envp != NULL, NULL); + g_return_val_if_fail (variable != NULL, NULL); + + index = ot_g_environ_find (envp, variable); + if (index != -1) + return envp[index] + strlen (variable) + 1; + else + return NULL; +} + +gchar ** +ot_g_environ_setenv (gchar **envp, + const gchar *variable, + const gchar *value, + gboolean overwrite) +{ + gint index; + + g_return_val_if_fail (envp != NULL, NULL); + g_return_val_if_fail (variable != NULL, NULL); + g_return_val_if_fail (strchr (variable, '=') == NULL, NULL); + + index = ot_g_environ_find (envp, variable); + if (index != -1) + { + if (overwrite) + { + g_free (envp[index]); + envp[index] = g_strdup_printf ("%s=%s", variable, value); + } + } + else + { + gint length; + + length = g_strv_length (envp); + envp = g_renew (gchar *, envp, length + 2); + envp[length] = g_strdup_printf ("%s=%s", variable, value); + envp[length + 1] = NULL; + } + + return envp; +} + +gchar ** +ot_g_environ_unsetenv (gchar **envp, + const gchar *variable) +{ + gint len; + gchar **e, **f; + + g_return_val_if_fail (envp != NULL, NULL); + g_return_val_if_fail (variable != NULL, NULL); + g_return_val_if_fail (strchr (variable, '=') == NULL, NULL); + + len = strlen (variable); + + /* Note that we remove *all* environment entries for + * the variable name, not just the first. + */ + e = f = envp; + while (*e != NULL) + { + if (strncmp (*e, variable, len) != 0 || (*e)[len] != '=') + { + *f = *e; + f++; + } + e++; + } + *f = NULL; + + return envp; +} + +#endif diff --git a/libotutil/ot-glib-compat.h b/libotutil/ot-glib-compat.h new file mode 100644 index 00000000..f33728e4 --- /dev/null +++ b/libotutil/ot-glib-compat.h @@ -0,0 +1,52 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2011 Colin Walters . + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Author: Colin Walters + */ + +#ifndef __OSTREE_GLIB_COMPAT_H__ +#define __OSTREE_GLIB_COMPAT_H__ + +#include + +G_BEGIN_DECLS + +#if GLIB_CHECK_VERSION(2,32,0) +#define ot_g_environ_getenv g_environ_getenv +#define ot_g_environ_setenv g_environ_setenv +#define ot_g_environ_unsetenv g_environ_unsetenv +#else +const gchar * +ot_g_environ_getenv (gchar **envp, + const gchar *variable); + +gchar ** +ot_g_environ_setenv (gchar **envp, + const gchar *variable, + const gchar *value, + gboolean overwrite); + +gchar ** +ot_g_environ_unsetenv (gchar **envp, + const gchar *variable); +#endif + + +G_END_DECLS + +#endif diff --git a/libotutil/ot-opt-utils.h b/libotutil/ot-opt-utils.h index b65996f4..5f4a10df 100644 --- a/libotutil/ot-opt-utils.h +++ b/libotutil/ot-opt-utils.h @@ -19,8 +19,8 @@ * Author: Colin Walters */ -#ifndef __OSTREE_GIO_UTILS_H__ -#define __OSTREE_GIO_UTILS_H__ +#ifndef __OSTREE_OPT_UTILS_H__ +#define __OSTREE_OPT_UTILS_H__ #include diff --git a/libotutil/ot-unix-utils.c b/libotutil/ot-unix-utils.c index 78243f7c..763f8a90 100644 --- a/libotutil/ot-unix-utils.c +++ b/libotutil/ot-unix-utils.c @@ -28,6 +28,8 @@ #include #include +#include +#include #include gboolean @@ -254,3 +256,17 @@ ot_util_open_file_read_at (int dirfd, const char *name, GError **error) ot_util_set_error_from_errno (error, errno); return fd; } + +void +ot_util_fatal_literal (const char *msg) +{ + g_printerr ("%s\n", msg); + exit (1); +} + +void +ot_util_fatal_gerror (GError *error) +{ + g_assert (error != NULL); + ot_util_fatal_literal (error->message); +} diff --git a/libotutil/ot-unix-utils.h b/libotutil/ot-unix-utils.h index 0e1d3926..d249d345 100644 --- a/libotutil/ot-unix-utils.h +++ b/libotutil/ot-unix-utils.h @@ -38,6 +38,10 @@ G_BEGIN_DECLS gboolean ot_util_spawn_pager (GOutputStream **out_stream, GError **error); +void ot_util_fatal_literal (const char *msg) G_GNUC_NORETURN; + +void ot_util_fatal_gerror (GError *error) G_GNUC_NORETURN; + gboolean ot_util_filename_has_dotdot (const char *path); GPtrArray *ot_util_sort_filenames_by_component_length (GPtrArray *files); diff --git a/libotutil/otutil.h b/libotutil/otutil.h index 2c49819a..dd115534 100644 --- a/libotutil/otutil.h +++ b/libotutil/otutil.h @@ -24,5 +24,6 @@ #include #include #include +#include #endif diff --git a/osbuild/main.c b/osbuild/main.c new file mode 100644 index 00000000..db6d26f3 --- /dev/null +++ b/osbuild/main.c @@ -0,0 +1,107 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2011 Colin Walters + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Author: Colin Walters + */ + +#include "config.h" + +#include + +#include + +#include "ob-builtins.h" + +static OsbuildBuiltin builtins[] = { + { "buildone", osbuild_builtin_buildone, 0 }, + { NULL } +}; + +static int +usage (char **argv, gboolean is_error) +{ + OsbuildBuiltin *builtin = builtins; + void (*print_func) (const gchar *format, ...); + + if (is_error) + print_func = g_printerr; + else + print_func = g_print; + + print_func ("usage: %s COMMAND [options]\n", + argv[0]); + print_func ("Builtin commands:\n"); + + while (builtin->name) + { + print_func (" %s\n", builtin->name); + builtin++; + } + return (is_error ? 1 : 0); +} + + +int +main (int argc, + char **argv) +{ + OsbuildBuiltin *builtin; + const char *cmd; + + g_type_init (); + + g_set_prgname (argv[0]); + + builtin = builtins; + + if (argc < 2) + return usage (argv, 1); + + cmd = argv[1]; + + while (builtin->name) + { + GError *error = NULL; + if (strcmp (cmd, builtin->name) == 0) + { + int i; + int tmp_argc; + char **tmp_argv; + + tmp_argc = argc - 1; + tmp_argv = g_new0 (char *, tmp_argc + 1); + + tmp_argv[0] = (char*)builtin->name; + for (i = 0; i < tmp_argc; i++) + tmp_argv[i+1] = argv[i+2]; + if (!builtin->fn (tmp_argc, tmp_argv, NULL, &error)) + { + g_free (tmp_argv); + g_printerr ("%s\n", error->message); + g_clear_error (&error); + return 1; + } + g_free (tmp_argv); + return 0; + } + builtin++; + } + + g_printerr ("Unknown command '%s'\n", cmd); + return usage (argv, 1); +} diff --git a/osbuild/ob-builtin-buildone.c b/osbuild/ob-builtin-buildone.c new file mode 100644 index 00000000..d2da5e90 --- /dev/null +++ b/osbuild/ob-builtin-buildone.c @@ -0,0 +1,134 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2011 Colin Walters + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Author: Colin Walters + */ + +#include "config.h" + +#include "otutil.h" +#include "ob-builtins.h" + +#include +#include +#include +#include + +static char *repo_path; +static char *ref; +static char *name; +static char *generator; +static char *resultdir; +static gboolean raw; + +static GOptionEntry options[] = { + { "repo", 0, 0, G_OPTION_ARG_FILENAME, &repo_path, "Repository path", "repo" }, + { "rev", 'r', 0, G_OPTION_ARG_STRING, &ref, "Build using this tree", "rev" }, + { "name", 0, 0, G_OPTION_ARG_STRING, &name, "Name of the source", "source" }, + { "generator", 0, 0, G_OPTION_ARG_FILENAME, &generator, "Script to run on installed tree", "script" }, + { "raw", 0, 0, G_OPTION_ARG_NONE, &raw, "Do not instantiate a tree, use current", NULL }, + { "resultdir", 0, 0, G_OPTION_ARG_FILENAME, &resultdir, "Directory for output artifacts", "dir" }, + { NULL } +}; + +static char * +get_tmpdir (void) +{ + char *tmp_prefix = g_strdup (g_getenv ("XDG_RUNTIME_DIR")); + char *ret; + + if (tmp_prefix) + { + ret = g_strdup_printf ("%s/osbuild", tmp_prefix); + } + else + { + tmp_prefix = g_strdup_printf ("/tmp/osbuild-%d", getuid ()); + if (!g_file_test (tmp_prefix, G_FILE_TEST_IS_DIR)) + { + if (!mkdir (tmp_prefix, 0755)) + { + g_printerr ("Failed to make logging directory %s\n", tmp_prefix); + exit (1); + } + } + ret = tmp_prefix; + tmp_prefix = NULL; + } + g_free (tmp_prefix); + return ret; +} + +static gboolean +open_log (const char *name, + GOutputStream **out_log, + GError **error) +{ + gboolean ret = FALSE; + char *tmpdir = NULL; + char *path = NULL; + GFile *logf = NULL; + GFileOutputStream *ret_log = NULL; + + path = g_strdup_printf ("%s/%s.log", tmpdir, name); + logf = ot_util_new_file_for_path (path); + + ret_log = g_file_replace (logf, NULL, FALSE, 0, NULL, error); + if (!ret_log) + goto out; + + ret = TRUE; + *out_log = (GOutputStream*)ret_log; + ret_log = NULL; + out: + g_free (path); + g_free (tmpdir); + g_clear_object (&logf); + g_clear_object (&ret_log); + return ret; +} + +gboolean +osbuild_builtin_buildone (int argc, char **argv, const char *prefix, GError **error) +{ + GOptionContext *context; + gboolean ret = FALSE; + char *tmpdir; + + context = g_option_context_new ("- Build current directory"); + g_option_context_add_main_entries (context, options, NULL); + + if (!g_option_context_parse (context, &argc, &argv, error)) + goto out; + + if (!raw && !repo_path) + { + ot_util_usage_error (context, "A result directory must be specified with --resultdir", error); + goto out; + } + + if (!generator) + generator = g_build_filename (LIBEXECDIR, "ostree", "generators", "default", NULL); + + + + out: + if (context) + g_option_context_free (context); + return ret; +} diff --git a/osbuild/ob-builtins.h b/osbuild/ob-builtins.h new file mode 100644 index 00000000..f21aafd4 --- /dev/null +++ b/osbuild/ob-builtins.h @@ -0,0 +1,43 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2011 Colin Walters + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Author: Colin Walters + */ + +#ifndef __OSBUILD_BUILTINS__ +#define __OSBUILD_BUILTINS__ + +#include + +G_BEGIN_DECLS + +typedef enum { + OSBUILD_BUILTIN_FLAG_NONE = 0, +} OsbuildBuiltinFlags; + +typedef struct { + const char *name; + gboolean (*fn) (int argc, char **argv, const char *prefix, GError **error); + int flags; /* OsbuildBuiltinFlags */ +} OsbuildBuiltin; + +gboolean osbuild_builtin_buildone (int argc, char **argv, const char *prefix, GError **error); + +G_END_DECLS + +#endif diff --git a/osbuild/osbuild-raw-makeinstall.c b/osbuild/osbuild-raw-makeinstall.c new file mode 100644 index 00000000..49013ed8 --- /dev/null +++ b/osbuild/osbuild-raw-makeinstall.c @@ -0,0 +1,189 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2011 Colin Walters + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Author: Colin Walters + */ + +#include "config.h" + +#include + +#include "otutil.h" + +#include +#include +#include +#include + +static const char * +find_first_file (GFileTest test, const char *name, ...) G_GNUC_NULL_TERMINATED; + +static const char * +find_first_file (GFileTest test, const char *name, ...) +{ + va_list args; + + va_start (args, name); + + do + { + if (g_file_test (name, test)) + break; + name = va_arg (args, const char *); + } + while (name != NULL); + + va_end (args); + + return name; +} + +static void +split_configure_make_args (int argc, + char **argv, + GPtrArray **out_configure_args, + GPtrArray **out_make_args, + GPtrArray **out_makeinstall_args) +{ + int i; + + *out_configure_args = g_ptr_array_new (); + *out_make_args = g_ptr_array_new (); + *out_makeinstall_args = g_ptr_array_new (); + + for (i = 1; i < argc; i++) + { + if (g_str_has_prefix (argv[i], "--")) + g_ptr_array_add (*out_configure_args, argv[i]); + else if (g_str_has_prefix (argv[i], "DESTDIR=")) + g_ptr_array_add (*out_makeinstall_args, argv[i]); + else + g_ptr_array_add (*out_make_args, argv[i]); + } +} + +static void +spawn_sync_or_fatal (char **args, char **env, GSpawnFlags flags) +{ + GError *error = NULL; + int estatus; + char **iter; + + g_print ("osbuild: running: "); + for (iter = args; *iter; iter++) + g_print ("%s ", *iter); + g_print ("\n"); + if (g_spawn_sync (NULL, args, env, flags, NULL, NULL, NULL, NULL, &estatus, &error)) + { + if (WIFEXITED (estatus) && WEXITSTATUS (estatus) == 0) + { + g_message ("Subprocess %s exited successfully\n", args[0]); + } + else + { + if (WIFEXITED (estatus)) + g_error ("Subprocess %s exited with code %d\n", args[0], WEXITSTATUS (estatus)); + else if (WIFSIGNALED (estatus)) + g_error ("Subprocess %s killed by signal %d\n", args[0], WTERMSIG (estatus)); + else + g_error ("Subprocess %s terminated with status %d\n", args[0], estatus); + exit (1); + } + } + else + { + g_error ("Failed to execute %s: %s\n", args[0], error->message); + exit (1); + } +} + +static void +ptr_array_extend (GPtrArray *dest, GPtrArray *to_append) +{ + int i; + + for (i = 0; i < to_append->len; i++) + g_ptr_array_add (dest, to_append->pdata[i]); +} + +int +main (int argc, + char **argv) +{ + GPtrArray *config_args; + GPtrArray *make_args; + GPtrArray *makeinstall_args; + GPtrArray *args; + int i; + char **subprocess_env; + GError *error = NULL; + + g_type_init (); + + g_set_prgname (argv[0]); + + args = g_ptr_array_new (); + + subprocess_env = g_get_environ (); + ot_g_environ_setenv (subprocess_env, "LANG", "C", TRUE); + ot_g_environ_unsetenv (subprocess_env, "LC_ALL"); + + split_configure_make_args (argc, argv, &config_args, &make_args, &makeinstall_args); + + if (!g_file_test ("./configure", G_FILE_TEST_IS_EXECUTABLE)) + { + const char *autogen; + char **autogen_env; + + autogen = find_first_file (G_FILE_TEST_IS_EXECUTABLE, "./autogen", "./autogen.sh"); + if (!autogen) + ot_util_fatal_literal ("No executable configure or autogen script found"); + + autogen_env = g_strdupv (subprocess_env); + ot_g_environ_setenv (autogen_env, "NOCONFIGURE", "1", TRUE); + + g_ptr_array_set_size (args, 0); + g_ptr_array_add (args, (char*) autogen); + g_ptr_array_add (args, NULL); + spawn_sync_or_fatal ((char**)args->pdata, autogen_env, 0); + } + + if (!g_file_test ("./configure", G_FILE_TEST_IS_EXECUTABLE)) + ot_util_fatal_literal ("autogen script failed to generate a configure script"); + + g_ptr_array_set_size (args, 0); + g_ptr_array_add (args, "./configure"); + ptr_array_extend (args, config_args); + g_ptr_array_add (args, NULL); + spawn_sync_or_fatal ((char**)args->pdata, subprocess_env, 0); + + g_ptr_array_set_size (args, 0); + g_ptr_array_add (args, "make"); + ptr_array_extend (args, make_args); + g_ptr_array_add (args, NULL); + spawn_sync_or_fatal ((char**)args->pdata, subprocess_env, G_SPAWN_SEARCH_PATH); + + g_ptr_array_set_size (args, 0); + g_ptr_array_add (args, "make"); + g_ptr_array_add (args, "install"); + ptr_array_extend (args, makeinstall_args); + g_ptr_array_add (args, NULL); + spawn_sync_or_fatal ((char**)args->pdata, subprocess_env, G_SPAWN_SEARCH_PATH); + + return 0; +}