summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/.gitignore1
-rw-r--r--src/coreutils-arch.c32
-rw-r--r--src/coreutils-dir.c32
-rw-r--r--src/coreutils-vdir.c32
-rw-r--r--src/coreutils.c205
-rw-r--r--src/kill.c6
-rw-r--r--src/local.mk61
-rw-r--r--src/readlink.c2
-rw-r--r--src/shuf.c2
-rw-r--r--src/timeout.c8
-rw-r--r--src/truncate.c2
11 files changed, 373 insertions, 10 deletions
diff --git a/src/.gitignore b/src/.gitignore
index e273bb867..e8bccbae5 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -12,6 +12,7 @@ chown
chroot
cksum
comm
+coreutils
cp
csplit
cut
diff --git a/src/coreutils-arch.c b/src/coreutils-arch.c
new file mode 100644
index 000000000..899cc937b
--- /dev/null
+++ b/src/coreutils-arch.c
@@ -0,0 +1,32 @@
+/* arch -- wrapper to uname with the right uname_mode.
+ Copyright (C) 2014 Free Software Foundation, Inc.
+
+ 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 3 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, see <http://www.gnu.org/licenses/>. */
+
+/* Written by Alex Deymo <deymo@chromium.org>. */
+
+#include <config.h>
+#include "system.h"
+
+#include "uname.h"
+/* Ensure that the main for uname is declared even if the tool is not being
+ built in this single-binary. */
+int _single_binary_main_uname (int argc, char** argv) ATTRIBUTE_NORETURN;
+int _single_binary_main_arch (int argc, char** argv) ATTRIBUTE_NORETURN;
+
+int _single_binary_main_arch (int argc, char** argv)
+{
+ uname_mode = UNAME_ARCH;
+ _single_binary_main_uname (argc, argv);
+}
diff --git a/src/coreutils-dir.c b/src/coreutils-dir.c
new file mode 100644
index 000000000..4b488f415
--- /dev/null
+++ b/src/coreutils-dir.c
@@ -0,0 +1,32 @@
+/* dir -- wrapper to ls with the right ls_mode.
+ Copyright (C) 2014 Free Software Foundation, Inc.
+
+ 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 3 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, see <http://www.gnu.org/licenses/>. */
+
+/* Written by Alex Deymo <deymo@chromium.org>. */
+
+#include <config.h>
+#include "system.h"
+
+#include "ls.h"
+/* Ensure that the main for ls is declared even if the tool is not being built
+ in this single-binary. */
+int _single_binary_main_ls (int argc, char** argv) ATTRIBUTE_NORETURN;
+int _single_binary_main_dir (int argc, char** argv) ATTRIBUTE_NORETURN;
+
+int _single_binary_main_dir (int argc, char** argv)
+{
+ ls_mode = LS_MULTI_COL;
+ _single_binary_main_ls (argc, argv);
+}
diff --git a/src/coreutils-vdir.c b/src/coreutils-vdir.c
new file mode 100644
index 000000000..036367f6d
--- /dev/null
+++ b/src/coreutils-vdir.c
@@ -0,0 +1,32 @@
+/* vdir -- wrapper to ls with the right ls_mode.
+ Copyright (C) 2014 Free Software Foundation, Inc.
+
+ 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 3 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, see <http://www.gnu.org/licenses/>. */
+
+/* Written by Alex Deymo <deymo@chromium.org>. */
+
+#include <config.h>
+#include "system.h"
+
+#include "ls.h"
+/* Ensure that the main for ls is declared even if the tool is not being built
+ in this single-binary. */
+int _single_binary_main_ls (int argc, char** argv) ATTRIBUTE_NORETURN;
+int _single_binary_main_vdir (int argc, char** argv) ATTRIBUTE_NORETURN;
+
+int _single_binary_main_vdir (int argc, char** argv)
+{
+ ls_mode = LS_LONG_FORMAT;
+ _single_binary_main_ls (argc, argv);
+}
diff --git a/src/coreutils.c b/src/coreutils.c
new file mode 100644
index 000000000..c459b1d62
--- /dev/null
+++ b/src/coreutils.c
@@ -0,0 +1,205 @@
+/* Copyright (C) 2014 Free Software Foundation, Inc.
+
+ 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 3 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, see <http://www.gnu.org/licenses/>. */
+
+/* coreutils.c aggregates the functionality of every other tool into a single
+ binary multiplexed by the value of argv[0]. This is enabled by passing
+ --enable-single-binary to configure.
+
+ Written by Alex Deymo <deymo@chromium.org>. */
+
+#include <config.h>
+#include <getopt.h>
+#include <stdio.h>
+#if HAVE_PRCTL
+# include <sys/prctl.h>
+#endif
+
+#include "system.h"
+#include "error.h"
+#include "quote.h"
+
+#ifdef SINGLE_BINARY
+/* Declare the main function on each one of the selected tools. This name
+ needs to match the one passed as CFLAGS on single-binary.mk (generated
+ by gen-single-binary.sh). */
+# define SINGLE_BINARY_PROGRAM(prog_name_str, main_name) \
+ int _single_binary_main_##main_name (int, char**) ATTRIBUTE_NORETURN;
+# include "coreutils.h"
+# undef SINGLE_BINARY_PROGRAM
+#endif
+
+/* The official name of this program (e.g., no 'g' prefix). */
+#define PROGRAM_NAME "coreutils"
+
+#define AUTHORS \
+ proper_name ("Alex Deymo")
+
+void
+launch_program (const char *prog_name, int prog_argc, char **prog_argv);
+
+static struct option const long_options[] =
+{
+ {GETOPT_HELP_OPTION_DECL},
+ {GETOPT_VERSION_OPTION_DECL},
+ {NULL, 0, NULL, 0}
+};
+
+
+void
+usage (int status)
+{
+ if (status != EXIT_SUCCESS)
+ emit_try_help ();
+ else
+ {
+ printf (_("\
+Usage: %s --coreutils-prog=PROGRAM_NAME [PARAMETERS]... \n"),
+ program_name);
+ fputs (_("\
+Execute the PROGRAM_NAME built-in program with the given PARAMETERS.\n\
+\n"), stdout);
+ fputs (HELP_OPTION_DESCRIPTION, stdout);
+ fputs (VERSION_OPTION_DESCRIPTION, stdout);
+
+ printf ("\n\
+Built-in programs:\n"
+#ifdef SINGLE_BINARY
+/* XXX: Ideally we#d like to present "install" here, not "ginstall". */
+# define SINGLE_BINARY_PROGRAM(prog_name_str, main_name) " " prog_name_str
+# include "coreutils.h"
+# undef SINGLE_BINARY_PROGRAM
+#endif
+ "\n");
+
+ printf (_("\
+\n\
+Use: '%s --coreutils-prog=PROGRAM_NAME --help' for individual program help.\n"),
+ program_name);
+ emit_ancillary_info ();
+ }
+ exit (status);
+}
+
+void
+launch_program (const char *prog_name, int prog_argc, char **prog_argv)
+{
+ int (*prog_main)(int, char **) = NULL;
+
+ /* Ensure that at least one parameter was passed. */
+ if (!prog_argc || !prog_argv || !prog_argv[0] || !prog_name)
+ return;
+
+#ifdef SINGLE_BINARY
+ if (false);
+ /* Lookup the right main program. */
+# define SINGLE_BINARY_PROGRAM(prog_name_str, main_name) \
+ else if (STREQ (prog_name_str, prog_name)) \
+ prog_main = _single_binary_main_##main_name;
+# include "coreutils.h"
+# undef SINGLE_BINARY_PROGRAM
+#endif
+
+ if (! prog_main)
+ return;
+
+#if HAVE_PRCTL && defined PR_SET_NAME
+ /* Not being able to set the program name is not a fatal error. */
+ prctl (PR_SET_NAME, prog_argv[0]);
+#endif
+#if HAVE_PRCTL && defined PR_SET_MM_ARG_START
+ /* Shift the beginning of the command line to prog_argv[0] (if set) so
+ /proc/pid/cmdline reflects the right value. */
+ prctl (PR_SET_MM_ARG_START, prog_argv[0]);
+#endif
+
+ exit ((*prog_main) (prog_argc, prog_argv));
+}
+
+int
+main (int argc, char **argv)
+{
+ char *prog_name = last_component (argv[0]);
+ int optc;
+
+ /* Map external name to internal name. */
+ char ginstall[] = "ginstall";
+ if (STREQ (prog_name, "install"))
+ prog_name = ginstall;
+
+ /* If this program is called directly as "coreutils" or if the value of
+ argv[0] is an unknown tool (which "coreutils" is), we proceed and parse
+ the options. */
+ launch_program (prog_name, argc, argv);
+
+ /* No known program was selected via argv[0]. Try parsing the first
+ argument as --coreutils-prog=PROGRAM to determine the program. The
+ invocation for this case should be:
+ path/to/coreutils --coreutils-prog=someprog someprog ...
+ The third argument is what the program will see as argv[0]. */
+
+ if (argc >= 2)
+ {
+ size_t nskip = 0;
+ char *arg_name = NULL;
+
+ /* If calling coreutils directly, the "script" name isn't passed.
+ Distinguish the two cases with a -shebang suffix. */
+ if (STRPREFIX (argv[1], "--coreutils-prog="))
+ {
+ nskip = 1;
+ arg_name = prog_name = argv[1] + strlen ("--coreutils-prog=");
+ }
+ else if (STRPREFIX (argv[1], "--coreutils-prog-shebang="))
+ {
+ nskip = 2;
+ prog_name = argv[1] + strlen ("--coreutils-prog-shebang=");
+ if (argc >= 3)
+ arg_name = last_component (argv[2]);
+ else
+ arg_name = prog_name;
+ }
+
+ if (nskip)
+ {
+ argv[nskip] = arg_name; /* XXX: Discards any specified path. */
+ launch_program (prog_name, argc - nskip, argv + nskip);
+ error (EXIT_FAILURE, 0, _("unknown program %s"), quote (prog_name));
+ }
+ }
+
+ /* No known program was selected. From here on, we behave like any other
+ coreutils program. */
+ initialize_main (&argc, &argv);
+ set_program_name (argv[0]);
+ setlocale (LC_ALL, "");
+ bindtextdomain (PACKAGE, LOCALEDIR);
+ textdomain (PACKAGE);
+ atexit (close_stdout);
+
+ if ((optc = getopt_long (argc, argv, "", long_options, NULL)) != -1)
+ switch (optc)
+ {
+ case_GETOPT_HELP_CHAR;
+
+ case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
+ }
+
+ /* Only print the error message when no options have been passed
+ to coreutils. */
+ if (optind == 1 && prog_name && !STREQ (prog_name, "coreutils"))
+ error (0, 0, _("unknown program %s"), quote (prog_name));
+
+ usage (EXIT_FAILURE);
+}
diff --git a/src/kill.c b/src/kill.c
index 4ab86a48f..724667e0e 100644
--- a/src/kill.c
+++ b/src/kill.c
@@ -306,7 +306,7 @@ main (int argc, char **argv)
usage (EXIT_FAILURE);
}
- return (list
- ? list_signals (table, optind < argc ? argv + optind : NULL)
- : send_signals (signum, argv + optind));
+ exit (list
+ ? list_signals (table, optind < argc ? argv + optind : NULL)
+ : send_signals (signum, argv + optind));
}
diff --git a/src/local.mk b/src/local.mk
index 865dd7452..e35d28688 100644
--- a/src/local.mk
+++ b/src/local.mk
@@ -42,6 +42,7 @@ noinst_PROGRAMS = \
noinst_HEADERS = \
src/chown-core.h \
src/copy.h \
+ src/coreutils.h \
src/cp-hash.h \
src/dircolors.h \
src/fiemap.h \
@@ -105,6 +106,9 @@ src_cksum_LDADD = $(LDADD)
src_comm_LDADD = $(LDADD)
src_nproc_LDADD = $(LDADD)
src_cp_LDADD = $(LDADD)
+if !SINGLE_BINARY
+src_coreutils_LDADD = $(LDADD)
+endif
src_csplit_LDADD = $(LDADD)
src_cut_LDADD = $(LDADD)
src_date_LDADD = $(LDADD)
@@ -150,6 +154,7 @@ src_mv_LDADD = $(LDADD)
src_nice_LDADD = $(LDADD)
src_nl_LDADD = $(LDADD)
src_nohup_LDADD = $(LDADD)
+src_numfmt_LDADD = $(LDADD)
src_od_LDADD = $(LDADD)
src_paste_LDADD = $(LDADD)
src_pathchk_LDADD = $(LDADD)
@@ -395,6 +400,46 @@ src_libstdbuf_so_LDADD = $(LIBINTL)
src_libstdbuf_so_LDFLAGS = -shared
src_libstdbuf_so_CFLAGS = -fPIC $(AM_CFLAGS)
+BUILT_SOURCES += src/coreutils.h
+if SINGLE_BINARY
+# Single binary dependencies
+src_coreutils_CFLAGS = -DSINGLE_BINARY $(AM_CFLAGS)
+#src_coreutils_LDFLAGS = $(AM_LDFLAGS)
+src_coreutils_LDADD = $(single_binary_deps) $(LDADD) $(single_binary_libs)
+src_coreutils_DEPENDENCIES = $(LDADD) $(single_binary_deps)
+
+include $(top_srcdir)/src/single-binary.mk
+
+# Creates symlinks or shebangs to the installed programs when building
+# coreutils single binary.
+EXTRA_src_coreutils_DEPENDENCIES = src/coreutils_$(single_binary_install_type)
+endif SINGLE_BINARY
+
+CLEANFILES += src/coreutils_symlinks
+src/coreutils_symlinks: Makefile
+ $(AM_V_GEN)touch $@
+ $(AM_V_at)for i in $(single_binary_progs); do \
+ rm -f src/$$i$(EXEEXT) || exit $$?; \
+ $(LN_S) -s coreutils$(EXEEXT) src/$$i$(EXEEXT) || exit $$?; \
+ done
+
+CLEANFILES += src/coreutils_shebangs
+src/coreutils_shebangs: Makefile
+ $(AM_V_GEN)touch $@
+ $(AM_V_at)for i in $(single_binary_progs); do \
+ rm -f src/$$i$(EXEEXT) || exit $$?; \
+ printf '#!%s --coreutils-prog-shebang=%s\n' \
+ $(abs_top_builddir)/src/coreutils$(EXEEXT) $$i \
+ >src/$$i$(EXEEXT) || exit $$?; \
+ chmod a+x,a-w src/$$i$(EXEEXT) || exit $$?; \
+ done
+
+clean-local:
+ $(AM_V_at)for i in $(single_binary_progs); do \
+ rm -f src/$$i$(EXEEXT) || exit $$?; \
+ done
+
+
BUILT_SOURCES += src/dircolors.h
src/dircolors.h: src/dcgen src/dircolors.hin
$(AM_V_GEN)rm -f $@ $@-t
@@ -515,6 +560,22 @@ src/version.h: Makefile
$(AM_V_at)chmod a-w $@t
$(AM_V_at)mv $@t $@
+# Generates a list of macro invocations like:
+# SINGLE_BINARY_PROGRAM(program_name_str, main_name)
+# once for each program list on $(single_binary_progs). Note that
+# for [ the macro invocation is:
+# SINGLE_BINARY_PROGRAM("[", _)
+CLEANFILES += src/coreutils.h
+src/coreutils.h: Makefile
+ $(AM_V_GEN)rm -f $@
+ $(AM_V_at)for prog in $(single_binary_progs); do \
+ prog=`basename $$prog`; \
+ main=`echo $$prog | tr '[' '_'`; \
+ echo "SINGLE_BINARY_PROGRAM(\"$$prog\", $$main)"; \
+ done | sort > $@t
+ $(AM_V_at)chmod a-w $@t
+ $(AM_V_at)mv $@t $@
+
DISTCLEANFILES += src/version.c src/version.h
MAINTAINERCLEANFILES += $(BUILT_SOURCES)
diff --git a/src/readlink.c b/src/readlink.c
index d63f07b40..f46d948e1 100644
--- a/src/readlink.c
+++ b/src/readlink.c
@@ -174,5 +174,5 @@ main (int argc, char **argv)
}
}
- return status;
+ exit (status);
}
diff --git a/src/shuf.c b/src/shuf.c
index 915f7b7a5..2505be6f1 100644
--- a/src/shuf.c
+++ b/src/shuf.c
@@ -622,5 +622,5 @@ main (int argc, char **argv)
}
#endif
- return EXIT_SUCCESS;
+ exit (EXIT_SUCCESS);
}
diff --git a/src/timeout.c b/src/timeout.c
index 23d894159..68baa23ce 100644
--- a/src/timeout.c
+++ b/src/timeout.c
@@ -440,7 +440,7 @@ main (int argc, char **argv)
if (monitored_pid == -1)
{
error (0, errno, _("fork system call failed"));
- return EXIT_CANCELED;
+ exit (EXIT_CANCELED);
}
else if (monitored_pid == 0)
{ /* child */
@@ -455,7 +455,7 @@ main (int argc, char **argv)
/* exit like sh, env, nohup, ... */
exit_status = (errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE);
error (0, errno, _("failed to run command %s"), quote (argv[0]));
- return exit_status;
+ exit (exit_status);
}
else
{
@@ -500,8 +500,8 @@ main (int argc, char **argv)
}
if (timed_out && !preserve_status)
- return EXIT_TIMEDOUT;
+ exit (EXIT_TIMEDOUT);
else
- return status;
+ exit (status);
}
}
diff --git a/src/truncate.c b/src/truncate.c
index 44d0b9670..f31250920 100644
--- a/src/truncate.c
+++ b/src/truncate.c
@@ -420,5 +420,5 @@ main (int argc, char **argv)
}
}
- return errors ? EXIT_FAILURE : EXIT_SUCCESS;
+ exit (errors ? EXIT_FAILURE : EXIT_SUCCESS);
}