From: Schantl Stefan Date: Sat, 27 Nov 2010 12:46:17 +0000 (+0100) Subject: coreutils: Update to 8.7. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1555d43c74d47dc74161dbceda0f0f23c475c2fc;p=ipfire-3.x.git coreutils: Update to 8.7. --- diff --git a/pkgs/core/coreutils/coreutils.nm b/pkgs/core/coreutils/coreutils.nm index b4972eeb8..d9fe8faa6 100644 --- a/pkgs/core/coreutils/coreutils.nm +++ b/pkgs/core/coreutils/coreutils.nm @@ -25,8 +25,8 @@ include $(PKGROOT)/Include PKG_NAME = coreutils -PKG_VER = 8.5 -PKG_REL = 2 +PKG_VER = 8.7 +PKG_REL = 0 PKG_MAINTAINER = PKG_GROUP = System/Base diff --git a/pkgs/core/coreutils/patches/coreutils-8.4-pam.patch b/pkgs/core/coreutils/patches/coreutils-8.4-pam.patch deleted file mode 100644 index e61908f3f..000000000 --- a/pkgs/core/coreutils/patches/coreutils-8.4-pam.patch +++ /dev/null @@ -1,428 +0,0 @@ -diff -urNp coreutils-8.4-orig/configure.ac coreutils-8.4/configure.ac ---- coreutils-8.4-orig/configure.ac 2010-01-11 18:20:42.000000000 +0100 -+++ coreutils-8.4/configure.ac 2010-02-12 10:17:46.000000000 +0100 -@@ -126,6 +126,13 @@ if test "$gl_gcc_warnings" = yes; then - AC_SUBST([GNULIB_WARN_CFLAGS]) - fi - -+dnl Give the chance to enable PAM -+AC_ARG_ENABLE(pam, dnl -+[ --enable-pam Enable use of the PAM libraries], -+[AC_DEFINE(USE_PAM, 1, [Define if you want to use PAM]) -+LIB_PAM="-ldl -lpam -lpam_misc" -+AC_SUBST(LIB_PAM)]) -+ - AC_FUNC_FORK - - optional_bin_progs= -diff -urNp coreutils-8.4-orig/doc/coreutils.texi coreutils-8.4/doc/coreutils.texi ---- coreutils-8.4-orig/doc/coreutils.texi 2010-01-03 18:06:20.000000000 +0100 -+++ coreutils-8.4/doc/coreutils.texi 2010-02-12 10:17:46.000000000 +0100 -@@ -15081,8 +15081,11 @@ to certain shells, etc.). - @findex syslog - @command{su} can optionally be compiled to use @code{syslog} to report - failed, and optionally successful, @command{su} attempts. (If the system --supports @code{syslog}.) However, GNU @command{su} does not check if the --user is a member of the @code{wheel} group; see below. -+supports @code{syslog}.) -+ -+This version of @command{su} has support for using PAM for -+authentication. You can edit @file{/etc/pam.d/su} to customize its -+behaviour. - - The program accepts the following options. Also see @ref{Common options}. - -@@ -15124,6 +15127,8 @@ environment variables except @env{TERM}, - @env{PATH} to a compiled-in default value. Change to @var{user}'s home - directory. Prepend @samp{-} to the shell's name, intended to make it - read its login startup file(s). -+Additionaly @env{DISPLAY} and @env{XAUTHORITY} environment variables -+are preserved as well for PAM functionality. - - @item -m - @itemx -p -@@ -15163,33 +15168,6 @@ Exit status: - the exit status of the subshell otherwise - @end display - --@cindex wheel group, not supported --@cindex group wheel, not supported --@cindex fascism --@subsection Why GNU @command{su} does not support the @samp{wheel} group -- --(This section is by Richard Stallman.) -- --@cindex Twenex --@cindex MIT AI lab --Sometimes a few of the users try to hold total power over all the --rest. For example, in 1984, a few users at the MIT AI lab decided to --seize power by changing the operator password on the Twenex system and --keeping it secret from everyone else. (I was able to thwart this coup --and give power back to the users by patching the kernel, but I --wouldn't know how to do that in Unix.) -- --However, occasionally the rulers do tell someone. Under the usual --@command{su} mechanism, once someone learns the root password who --sympathizes with the ordinary users, he or she can tell the rest. The --``wheel group'' feature would make this impossible, and thus cement the --power of the rulers. -- --I'm on the side of the masses, not that of the rulers. If you are --used to supporting the bosses and sysadmins in whatever they do, you --might find this idea strange at first. -- -- - @node timeout invocation - @section @command{timeout}: Run a command with a time limit - -diff -urNp coreutils-8.4-orig/src/Makefile.am coreutils-8.4/src/Makefile.am ---- coreutils-8.4-orig/src/Makefile.am 2010-01-03 18:06:20.000000000 +0100 -+++ coreutils-8.4/src/Makefile.am 2010-02-12 10:17:46.000000000 +0100 -@@ -361,7 +361,7 @@ factor_LDADD += $(LIB_GMP) - uptime_LDADD += $(GETLOADAVG_LIBS) - - # for crypt --su_LDADD += $(LIB_CRYPT) -+su_LDADD += $(LIB_CRYPT) @LIB_PAM@ - - # for various ACL functions - copy_LDADD += $(LIB_ACL) -diff -urNp coreutils-8.4-orig/src/su.c coreutils-8.4/src/su.c ---- coreutils-8.4-orig/src/su.c 2010-02-12 10:15:15.000000000 +0100 -+++ coreutils-8.4/src/su.c 2010-02-12 10:24:29.000000000 +0100 -@@ -37,6 +37,16 @@ - restricts who can su to UID 0 accounts. RMS considers that to - be fascist. - -+#ifdef USE_PAM -+ -+ Actually, with PAM, su has nothing to do with whether or not a -+ wheel group is enforced by su. RMS tries to restrict your access -+ to a su which implements the wheel group, but PAM considers that -+ to be fascist, and gives the user/sysadmin the opportunity to -+ enforce a wheel group by proper editing of /etc/pam.conf -+ -+#endif -+ - Compile-time options: - -DSYSLOG_SUCCESS Log successful su's (by default, to root) with syslog. - -DSYSLOG_FAILURE Log failed su's (by default, to root) with syslog. -@@ -53,6 +63,15 @@ - #include - #include - -+#ifdef USE_PAM -+# include -+# include -+# include -+# include -+# include -+# include -+#endif /* USE_PAM */ -+ - #include "system.h" - #include "getpass.h" - -@@ -120,10 +139,17 @@ - /* The user to become if none is specified. */ - #define DEFAULT_USER "root" - -+#ifndef USE_PAM - char *crypt (char const *key, char const *salt); -+#endif - --static void run_shell (char const *, char const *, char **, size_t) -+static void run_shell (char const *, char const *, char **, size_t, -+ const struct passwd *) -+#ifdef USE_PAM -+ ; -+#else - ATTRIBUTE_NORETURN; -+#endif - - /* If true, pass the `-f' option to the subshell. */ - static bool fast_startup; -@@ -209,7 +235,26 @@ log_su (struct passwd const *pw, bool su - } - #endif - -+#ifdef USE_PAM -+static pam_handle_t *pamh = NULL; -+static int retval; -+static struct pam_conv conv = { -+ misc_conv, -+ NULL -+}; -+ -+#define PAM_BAIL_P if (retval) { \ -+ pam_end(pamh, PAM_SUCCESS); \ -+ return 0; \ -+} -+#define PAM_BAIL_P_VOID if (retval) { \ -+ pam_end(pamh, PAM_SUCCESS); \ -+return; \ -+} -+#endif -+ - /* Ask the user for a password. -+ If PAM is in use, let PAM ask for the password if necessary. - Return true if the user gives the correct password for entry PW, - false if not. Return true without asking for a password if run by UID 0 - or if PW has an empty password. */ -@@ -217,6 +262,44 @@ log_su (struct passwd const *pw, bool su - static bool - correct_password (const struct passwd *pw) - { -+#ifdef USE_PAM -+ struct passwd *caller; -+ char *tty_name, *ttyn; -+ retval = pam_start(PROGRAM_NAME, pw->pw_name, &conv, &pamh); -+ PAM_BAIL_P; -+ -+ if (getuid() != 0 && !isatty(0)) { -+ fprintf(stderr, "standard in must be a tty\n"); -+ exit(1); -+ } -+ -+ caller = getpwuid(getuid()); -+ if(caller != NULL && caller->pw_name != NULL) { -+ retval = pam_set_item(pamh, PAM_RUSER, caller->pw_name); -+ PAM_BAIL_P; -+ } -+ -+ ttyn = ttyname(0); -+ if (ttyn) { -+ if (strncmp(ttyn, "/dev/", 5) == 0) -+ tty_name = ttyn+5; -+ else -+ tty_name = ttyn; -+ retval = pam_set_item(pamh, PAM_TTY, tty_name); -+ PAM_BAIL_P; -+ } -+ retval = pam_authenticate(pamh, 0); -+ PAM_BAIL_P; -+ retval = pam_acct_mgmt(pamh, 0); -+ if (retval == PAM_NEW_AUTHTOK_REQD) { -+ /* password has expired. Offer option to change it. */ -+ retval = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK); -+ PAM_BAIL_P; -+ } -+ PAM_BAIL_P; -+ /* must be authenticated if this point was reached */ -+ return 1; -+#else /* !USE_PAM */ - char *unencrypted, *encrypted, *correct; - #if HAVE_GETSPNAM && HAVE_STRUCT_SPWD_SP_PWDP - /* Shadow passwd stuff for SVR3 and maybe other systems. */ -@@ -241,6 +324,7 @@ correct_password (const struct passwd *p - encrypted = crypt (unencrypted, correct); - memset (unencrypted, 0, strlen (unencrypted)); - return STREQ (encrypted, correct); -+#endif /* !USE_PAM */ - } - - /* Update `environ' for the new shell based on PW, with SHELL being -@@ -254,12 +338,18 @@ modify_environment (const struct passwd - /* Leave TERM unchanged. Set HOME, SHELL, USER, LOGNAME, PATH. - Unset all other environment variables. */ - char const *term = getenv ("TERM"); -+ char const *display = getenv ("DISPLAY"); -+ char const *xauthority = getenv ("XAUTHORITY"); - if (term) - term = xstrdup (term); - environ = xmalloc ((6 + !!term) * sizeof (char *)); - environ[0] = NULL; - if (term) - xsetenv ("TERM", term); -+ if (display) -+ xsetenv ("DISPLAY", display); -+ if (xauthority) -+ xsetenv ("XAUTHORITY", xauthority); - xsetenv ("HOME", pw->pw_dir); - xsetenv ("SHELL", shell); - xsetenv ("USER", pw->pw_name); -@@ -292,8 +382,13 @@ change_identity (const struct passwd *pw - { - #ifdef HAVE_INITGROUPS - errno = 0; -- if (initgroups (pw->pw_name, pw->pw_gid) == -1) -+ if (initgroups (pw->pw_name, pw->pw_gid) == -1) { -+#ifdef USE_PAM -+ pam_close_session(pamh, 0); -+ pam_end(pamh, PAM_ABORT); -+#endif - error (EXIT_CANCELED, errno, _("cannot set groups")); -+ } - endgrent (); - #endif - if (setgid (pw->pw_gid)) -@@ -302,6 +397,31 @@ change_identity (const struct passwd *pw - error (EXIT_CANCELED, errno, _("cannot set user id")); - } - -+#ifdef USE_PAM -+static int caught=0; -+/* Signal handler for parent process later */ -+static void su_catch_sig(int sig) -+{ -+ ++caught; -+} -+ -+int -+pam_copyenv (pam_handle_t *pamh) -+{ -+ char **env; -+ -+ env = pam_getenvlist(pamh); -+ if(env) { -+ while(*env) { -+ if (putenv (*env)) -+ xalloc_die (); -+ env++; -+ } -+ } -+ return(0); -+} -+#endif -+ - /* Run SHELL, or DEFAULT_SHELL if SHELL is empty. - If COMMAND is nonzero, pass it to the shell with the -c option. - Pass ADDITIONAL_ARGS to the shell as more arguments; there -@@ -309,17 +429,49 @@ change_identity (const struct passwd *pw - - static void - run_shell (char const *shell, char const *command, char **additional_args, -- size_t n_additional_args) -+ size_t n_additional_args, const struct passwd *pw) - { - size_t n_args = 1 + fast_startup + 2 * !!command + n_additional_args + 1; - char const **args = xnmalloc (n_args, sizeof *args); - size_t argno = 1; -+#ifdef USE_PAM -+ int child; -+ sigset_t ourset; -+ int status; -+ -+ retval = pam_open_session(pamh,0); -+ if (retval != PAM_SUCCESS) { -+ fprintf (stderr, "could not open session\n"); -+ exit (1); -+ } -+ -+/* do this at the last possible moment, because environment variables may -+ be passed even in the session phase -+*/ -+ if(pam_copyenv(pamh) != PAM_SUCCESS) -+ fprintf (stderr, "error copying PAM environment\n"); -+ -+ /* Credentials should be set in the parent */ -+ if (pam_setcred(pamh, PAM_ESTABLISH_CRED) != PAM_SUCCESS) { -+ pam_close_session(pamh, 0); -+ fprintf(stderr, "could not set PAM credentials\n"); -+ exit(1); -+ } -+ -+ child = fork(); -+ if (child == 0) { /* child shell */ -+ change_identity (pw); -+ pam_end(pamh, 0); -+#endif - - if (simulate_login) - { - char *arg0; - char *shell_basename; - -+ if(chdir(pw->pw_dir)) -+ error(0, errno, _("warning: cannot change directory to %s"), pw->pw_dir); -+ - shell_basename = last_component (shell); - arg0 = xmalloc (strlen (shell_basename) + 2); - arg0[0] = '-'; -@@ -344,6 +496,67 @@ run_shell (char const *shell, char const - error (0, errno, "%s", shell); - exit (exit_status); - } -+#ifdef USE_PAM -+ } else if (child == -1) { -+ fprintf(stderr, "can not fork user shell: %s", strerror(errno)); -+ pam_setcred(pamh, PAM_DELETE_CRED | PAM_SILENT); -+ pam_close_session(pamh, 0); -+ pam_end(pamh, PAM_ABORT); -+ exit(1); -+ } -+ /* parent only */ -+ sigfillset(&ourset); -+ if (sigprocmask(SIG_BLOCK, &ourset, NULL)) { -+ fprintf(stderr, "%s: signal malfunction\n", PROGRAM_NAME); -+ caught = 1; -+ } -+ if (!caught) { -+ struct sigaction action; -+ action.sa_handler = su_catch_sig; -+ sigemptyset(&action.sa_mask); -+ action.sa_flags = 0; -+ sigemptyset(&ourset); -+ if (sigaddset(&ourset, SIGTERM) -+ || sigaddset(&ourset, SIGALRM) -+ || sigaction(SIGTERM, &action, NULL) -+ || sigprocmask(SIG_UNBLOCK, &ourset, NULL)) { -+ fprintf(stderr, "%s: signal masking malfunction\n", PROGRAM_NAME); -+ caught = 1; -+ } -+ } -+ if (!caught) { -+ do { -+ int pid; -+ -+ pid = waitpid(-1, &status, WUNTRACED); -+ -+ if (((pid_t)-1 != pid) && (0 != WIFSTOPPED (status))) { -+ kill(getpid(), WSTOPSIG(status)); -+ /* once we get here, we must have resumed */ -+ kill(pid, SIGCONT); -+ } -+ } while (0 != WIFSTOPPED(status)); -+ } -+ -+ if (caught) { -+ fprintf(stderr, "\nSession terminated, killing shell..."); -+ kill (child, SIGTERM); -+ } -+ /* Not checking retval on this because we need to call close session */ -+ pam_setcred(pamh, PAM_DELETE_CRED | PAM_SILENT); -+ retval = pam_close_session(pamh, 0); -+ PAM_BAIL_P_VOID; -+ retval = pam_end(pamh, PAM_SUCCESS); -+ PAM_BAIL_P_VOID; -+ if (caught) { -+ sleep(2); -+ kill(child, SIGKILL); -+ fprintf(stderr, " ...killed.\n"); -+ exit(-1); -+ } -+ exit ((0 != WIFEXITED (status)) ? WEXITSTATUS (status) -+ : WTERMSIG (status) + 128); -+#endif /* USE_PAM */ - } - - /* Return true if SHELL is a restricted shell (one not returned by -@@ -511,9 +724,9 @@ main (int argc, char **argv) - shell = xstrdup (shell ? shell : pw->pw_shell); - modify_environment (pw, shell); - -+#ifndef USE_PAM - change_identity (pw); -- if (simulate_login && chdir (pw->pw_dir) != 0) -- error (0, errno, _("warning: cannot change directory to %s"), pw->pw_dir); -+#endif - - /* error() flushes stderr, but does not check for write failure. - Normally, we would catch this via our atexit() hook of -@@ -523,5 +736,5 @@ main (int argc, char **argv) - if (ferror (stderr)) - exit (EXIT_CANCELED); - -- run_shell (shell, command, argv + optind, MAX (0, argc - optind)); -+ run_shell (shell, command, argv + optind, MAX (0, argc - optind), pw); - } diff --git a/pkgs/core/coreutils/patches/coreutils-8.5-pam.patch b/pkgs/core/coreutils/patches/coreutils-8.5-pam.patch new file mode 100644 index 000000000..71b85e7a4 --- /dev/null +++ b/pkgs/core/coreutils/patches/coreutils-8.5-pam.patch @@ -0,0 +1,428 @@ +From ea2d050b1952feb99f86c98255280beb6e589d8c Mon Sep 17 00:00:00 2001 +From: Ludwig Nussel +Date: Tue, 17 Aug 2010 13:21:44 +0200 +Subject: [PATCH 1/7] pam support for su + +--- + configure.ac | 14 +++ + src/Makefile.am | 4 +- + src/su.c | 266 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- + 3 files changed, 278 insertions(+), 6 deletions(-) + +diff --git a/configure.ac b/configure.ac +index b07a52b..1fb5839 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -128,6 +128,20 @@ fi + + AC_FUNC_FORK + ++AC_ARG_ENABLE(pam, AS_HELP_STRING([--disable-pam], ++ [Disable PAM support in su (default=auto)]), , [enable_pam=yes]) ++if test "x$enable_pam" != xno; then ++ AC_CHECK_LIB([pam], [pam_start], [enable_pam=yes], [enable_pam=no]) ++ AC_CHECK_LIB([pam_misc], [misc_conv], [:], [enable_pam=no]) ++ if test "x$enable_pam" != xno; then ++ AC_DEFINE(USE_PAM, 1, [Define if you want to use PAM]) ++ PAM_LIBS="-lpam -lpam_misc" ++ AC_SUBST(PAM_LIBS) ++ fi ++fi ++AC_MSG_CHECKING([whether to enable PAM support in su]) ++AC_MSG_RESULT([$enable_pam]) ++ + optional_bin_progs= + AC_CHECK_FUNCS([chroot], + gl_ADD_PROG([optional_bin_progs], [chroot])) +diff --git a/src/Makefile.am b/src/Makefile.am +index db5359b..154a5ed 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -363,8 +363,8 @@ factor_LDADD += $(LIB_GMP) + # for getloadavg + uptime_LDADD += $(GETLOADAVG_LIBS) + +-# for crypt +-su_LDADD += $(LIB_CRYPT) ++# for crypt and pam ++su_LDADD += $(LIB_CRYPT) $(PAM_LIBS) + + # for various ACL functions + copy_LDADD += $(LIB_ACL) +diff --git a/src/su.c b/src/su.c +index f8f5b61..811aad7 100644 +--- a/src/su.c ++++ b/src/su.c +@@ -37,6 +37,16 @@ + restricts who can su to UID 0 accounts. RMS considers that to + be fascist. + ++#ifdef USE_PAM ++ ++ Actually, with PAM, su has nothing to do with whether or not a ++ wheel group is enforced by su. RMS tries to restrict your access ++ to a su which implements the wheel group, but PAM considers that ++ to be fascist, and gives the user/sysadmin the opportunity to ++ enforce a wheel group by proper editing of /etc/pam.d/su ++ ++#endif ++ + Compile-time options: + -DSYSLOG_SUCCESS Log successful su's (by default, to root) with syslog. + -DSYSLOG_FAILURE Log failed su's (by default, to root) with syslog. +@@ -52,6 +62,13 @@ + #include + #include + #include ++#ifdef USE_PAM ++#include ++#include ++#include ++#include ++#include ++#endif + + #include "system.h" + #include "getpass.h" +@@ -111,7 +128,9 @@ + /* The user to become if none is specified. */ + #define DEFAULT_USER "root" + ++#ifndef USE_PAM + char *crypt (char const *key, char const *salt); ++#endif + + static void run_shell (char const *, char const *, char **, size_t) + ATTRIBUTE_NORETURN; +@@ -125,6 +144,11 @@ static bool simulate_login; + /* If true, change some environment vars to indicate the user su'd to. */ + static bool change_environment; + ++#ifdef USE_PAM ++static bool _pam_session_opened; ++static bool _pam_cred_established; ++#endif ++ + static struct option const longopts[] = + { + {"command", required_argument, NULL, 'c'}, +@@ -200,7 +224,164 @@ log_su (struct passwd const *pw, bool successful) + } + #endif + ++#ifdef USE_PAM ++#define PAM_SERVICE_NAME PROGRAM_NAME ++#define PAM_SERVICE_NAME_L PROGRAM_NAME "-l" ++static sig_atomic_t volatile caught_signal = false; ++static pam_handle_t *pamh = NULL; ++static int retval; ++static struct pam_conv conv = ++{ ++ misc_conv, ++ NULL ++}; ++ ++#define PAM_BAIL_P(a) \ ++ if (retval) \ ++ { \ ++ pam_end (pamh, retval); \ ++ a; \ ++ } ++ ++static void ++cleanup_pam (int retcode) ++{ ++ if (_pam_session_opened) ++ pam_close_session (pamh, 0); ++ ++ if (_pam_cred_established) ++ pam_setcred (pamh, PAM_DELETE_CRED | PAM_SILENT); ++ ++ pam_end(pamh, retcode); ++} ++ ++/* Signal handler for parent process. */ ++static void ++su_catch_sig (int sig) ++{ ++ caught_signal = true; ++} ++ ++/* Export env variables declared by PAM modules. */ ++static void ++export_pamenv (void) ++{ ++ char **env; ++ ++ /* This is a copy but don't care to free as we exec later anyways. */ ++ env = pam_getenvlist (pamh); ++ while (env && *env) ++ { ++ if (putenv (*env) != 0) ++ xalloc_die (); ++ env++; ++ } ++} ++ ++static void ++create_watching_parent (void) ++{ ++ pid_t child; ++ sigset_t ourset; ++ int status = 0; ++ ++ retval = pam_open_session (pamh, 0); ++ if (retval != PAM_SUCCESS) ++ { ++ cleanup_pam (retval); ++ error (EXIT_FAILURE, 0, _("cannot not open session: %s"), ++ pam_strerror (pamh, retval)); ++ } ++ else ++ _pam_session_opened = 1; ++ ++ child = fork (); ++ if (child == (pid_t) -1) ++ { ++ cleanup_pam (PAM_ABORT); ++ error (EXIT_FAILURE, errno, _("cannot create child process")); ++ } ++ ++ /* the child proceeds to run the shell */ ++ if (child == 0) ++ return; ++ ++ /* In the parent watch the child. */ ++ ++ /* su without pam support does not have a helper that keeps ++ sitting on any directory so let's go to /. */ ++ if (chdir ("/") != 0) ++ error (0, errno, _("warning: cannot change directory to %s"), "/"); ++ ++ sigfillset (&ourset); ++ if (sigprocmask (SIG_BLOCK, &ourset, NULL)) ++ { ++ error (0, errno, _("cannot block signals")); ++ caught_signal = true; ++ } ++ if (!caught_signal) ++ { ++ struct sigaction action; ++ action.sa_handler = su_catch_sig; ++ sigemptyset (&action.sa_mask); ++ action.sa_flags = 0; ++ sigemptyset (&ourset); ++ if (sigaddset (&ourset, SIGTERM) ++ || sigaddset (&ourset, SIGALRM) ++ || sigaction (SIGTERM, &action, NULL) ++ || sigprocmask (SIG_UNBLOCK, &ourset, NULL)) ++ { ++ error (0, errno, _("cannot set signal handler")); ++ caught_signal = true; ++ } ++ } ++ if (!caught_signal) ++ { ++ pid_t pid; ++ for (;;) ++ { ++ pid = waitpid (child, &status, WUNTRACED); ++ ++ if (pid != (pid_t)-1 && WIFSTOPPED (status)) ++ { ++ kill (getpid (), SIGSTOP); ++ /* once we get here, we must have resumed */ ++ kill (pid, SIGCONT); ++ } ++ else ++ break; ++ } ++ if (pid != (pid_t)-1) ++ if (WIFSIGNALED (status)) ++ status = WTERMSIG (status) + 128; ++ else ++ status = WEXITSTATUS (status); ++ else ++ status = 1; ++ } ++ else ++ status = 1; ++ ++ if (caught_signal) ++ { ++ fprintf (stderr, _("\nSession terminated, killing shell...")); ++ kill (child, SIGTERM); ++ } ++ ++ cleanup_pam (PAM_SUCCESS); ++ ++ if (caught_signal) ++ { ++ sleep (2); ++ kill (child, SIGKILL); ++ fprintf (stderr, _(" ...killed.\n")); ++ } ++ exit (status); ++} ++#endif ++ + /* Ask the user for a password. ++ If PAM is in use, let PAM ask for the password if necessary. + Return true if the user gives the correct password for entry PW, + false if not. Return true without asking for a password if run by UID 0 + or if PW has an empty password. */ +@@ -208,10 +389,52 @@ log_su (struct passwd const *pw, bool successful) + static bool + correct_password (const struct passwd *pw) + { ++#ifdef USE_PAM ++ const struct passwd *lpw; ++ const char *cp; ++ ++ retval = pam_start (simulate_login ? PAM_SERVICE_NAME_L : PAM_SERVICE_NAME, ++ pw->pw_name, &conv, &pamh); ++ PAM_BAIL_P (return false); ++ ++ if (isatty (0) && (cp = ttyname (0)) != NULL) ++ { ++ const char *tty; ++ ++ if (strncmp (cp, "/dev/", 5) == 0) ++ tty = cp + 5; ++ else ++ tty = cp; ++ retval = pam_set_item (pamh, PAM_TTY, tty); ++ PAM_BAIL_P (return false); ++ } ++#if 0 /* Manpage discourages use of getlogin. */ ++ cp = getlogin (); ++ if (!(cp && *cp && (lpw = getpwnam (cp)) != NULL && lpw->pw_uid == getuid ())) ++#endif ++ lpw = getpwuid (getuid ()); ++ if (lpw && lpw->pw_name) ++ { ++ retval = pam_set_item (pamh, PAM_RUSER, (const void *) lpw->pw_name); ++ PAM_BAIL_P (return false); ++ } ++ retval = pam_authenticate (pamh, 0); ++ PAM_BAIL_P (return false); ++ retval = pam_acct_mgmt (pamh, 0); ++ if (retval == PAM_NEW_AUTHTOK_REQD) ++ { ++ /* Password has expired. Offer option to change it. */ ++ retval = pam_chauthtok (pamh, PAM_CHANGE_EXPIRED_AUTHTOK); ++ PAM_BAIL_P (return false); ++ } ++ PAM_BAIL_P (return false); ++ /* Must be authenticated if this point was reached. */ ++ return true; ++#else /* !USE_PAM */ + char *unencrypted, *encrypted, *correct; + #if HAVE_GETSPNAM && HAVE_STRUCT_SPWD_SP_PWDP + /* Shadow passwd stuff for SVR3 and maybe other systems. */ +- struct spwd *sp = getspnam (pw->pw_name); ++ const struct spwd *sp = getspnam (pw->pw_name); + + endspent (); + if (sp) +@@ -232,6 +455,7 @@ correct_password (const struct passwd *pw) + encrypted = crypt (unencrypted, correct); + memset (unencrypted, 0, strlen (unencrypted)); + return STREQ (encrypted, correct); ++#endif /* !USE_PAM */ + } + + /* Update `environ' for the new shell based on PW, with SHELL being +@@ -274,19 +498,41 @@ modify_environment (const struct passwd *pw, const char *shell) + } + } + } ++ ++#ifdef USE_PAM ++ export_pamenv (); ++#endif + } + + /* Become the user and group(s) specified by PW. */ + + static void +-change_identity (const struct passwd *pw) ++init_groups (const struct passwd *pw) + { + #ifdef HAVE_INITGROUPS + errno = 0; + if (initgroups (pw->pw_name, pw->pw_gid) == -1) +- error (EXIT_CANCELED, errno, _("cannot set groups")); ++ { ++#ifdef USE_PAM ++ cleanup_pam (PAM_ABORT); ++#endif ++ error (EXIT_FAILURE, errno, _("cannot set groups")); ++ } + endgrent (); + #endif ++ ++#ifdef USE_PAM ++ retval = pam_setcred (pamh, PAM_ESTABLISH_CRED); ++ if (retval != PAM_SUCCESS) ++ error (EXIT_FAILURE, 0, "%s", pam_strerror (pamh, retval)); ++ else ++ _pam_cred_established = 1; ++#endif ++} ++ ++static void ++change_identity (const struct passwd *pw) ++{ + if (setgid (pw->pw_gid)) + error (EXIT_CANCELED, errno, _("cannot set group id")); + if (setuid (pw->pw_uid)) +@@ -500,9 +746,21 @@ main (int argc, char **argv) + shell = NULL; + } + shell = xstrdup (shell ? shell : pw->pw_shell); +- modify_environment (pw, shell); ++ ++ init_groups (pw); ++ ++#ifdef USE_PAM ++ create_watching_parent (); ++ /* Now we're in the child. */ ++#endif + + change_identity (pw); ++ ++ /* Set environment after pam_open_session, which may put KRB5CCNAME ++ into the pam_env, etc. */ ++ ++ modify_environment (pw, shell); ++ + if (simulate_login && chdir (pw->pw_dir) != 0) + error (0, errno, _("warning: cannot change directory to %s"), pw->pw_dir); + +-- +1.7.1 +diff -urNp coreutils-8.7-orig/doc/coreutils.texi coreutils-8.7/doc/coreutils.texi +--- coreutils-8.7-orig/doc/coreutils.texi 2010-11-15 12:47:03.529922880 +0100 ++++ coreutils-8.7/doc/coreutils.texi 2010-11-15 12:49:55.945171380 +0100 +@@ -15180,7 +15180,9 @@ the exit status of @var{command} otherwi + + @command{su} allows one user to temporarily become another user. It runs a + command (often an interactive shell) with the real and effective user +-ID, group ID, and supplemental groups of a given @var{user}. Synopsis: ++ID, group ID, and supplemental groups of a given @var{user}. When the -l ++option is given, the su-l PAM file is used instead of the default su PAM file. ++Synopsis: + + @example + su [@var{option}]@dots{} [@var{user} [@var{arg}]@dots{}] +@@ -15259,7 +15261,8 @@ environment variables except @env{TERM}, + (which are set, even for the super-user, as described above), and set + @env{PATH} to a compiled-in default value. Change to @var{user}'s home + directory. Prepend @samp{-} to the shell's name, intended to make it +-read its login startup file(s). ++read its login startup file(s). When this option is given, /etc/pam.d/su-l ++PAM file is used instead of the default one. + + @item -m + @itemx -p diff --git a/pkgs/core/coreutils/patches/coreutils-8.5-i18n.patch b/pkgs/core/coreutils/patches/coreutils-i18n.patch similarity index 89% rename from pkgs/core/coreutils/patches/coreutils-8.5-i18n.patch rename to pkgs/core/coreutils/patches/coreutils-i18n.patch index d6e6c4677..9c8543966 100644 --- a/pkgs/core/coreutils/patches/coreutils-8.5-i18n.patch +++ b/pkgs/core/coreutils/patches/coreutils-i18n.patch @@ -1,6 +1,6 @@ -diff -urNp coreutils-8.5-orig/lib/linebuffer.h coreutils-8.5/lib/linebuffer.h ---- coreutils-8.5-orig/lib/linebuffer.h 2010-04-23 15:44:00.000000000 +0200 -+++ coreutils-8.5/lib/linebuffer.h 2010-04-26 14:24:33.000000000 +0200 +diff -urNp coreutils-8.7-orig/lib/linebuffer.h coreutils-8.7/lib/linebuffer.h +--- coreutils-8.7-orig/lib/linebuffer.h 2010-06-10 18:45:26.000000000 +0200 ++++ coreutils-8.7/lib/linebuffer.h 2010-11-15 09:59:36.974172148 +0100 @@ -21,6 +21,11 @@ # include @@ -23,9 +23,9 @@ diff -urNp coreutils-8.5-orig/lib/linebuffer.h coreutils-8.5/lib/linebuffer.h }; /* Initialize linebuffer LINEBUFFER for use. */ -diff -urNp coreutils-8.5-orig/src/cut.c coreutils-8.5/src/cut.c ---- coreutils-8.5-orig/src/cut.c 2010-04-20 21:52:04.000000000 +0200 -+++ coreutils-8.5/src/cut.c 2010-04-26 14:24:33.000000000 +0200 +diff -urNp coreutils-8.7-orig/src/cut.c coreutils-8.7/src/cut.c +--- coreutils-8.7-orig/src/cut.c 2010-10-11 19:35:11.000000000 +0200 ++++ coreutils-8.7/src/cut.c 2010-11-15 09:59:36.976171659 +0100 @@ -28,6 +28,11 @@ #include #include @@ -38,7 +38,7 @@ diff -urNp coreutils-8.5-orig/src/cut.c coreutils-8.5/src/cut.c #include "system.h" #include "error.h" -@@ -36,6 +41,18 @@ +@@ -37,6 +42,18 @@ #include "quote.h" #include "xstrndup.h" @@ -57,7 +57,7 @@ diff -urNp coreutils-8.5-orig/src/cut.c coreutils-8.5/src/cut.c /* The official name of this program (e.g., no `g' prefix). */ #define PROGRAM_NAME "cut" -@@ -71,6 +88,52 @@ +@@ -72,6 +89,52 @@ } \ while (0) @@ -110,7 +110,7 @@ diff -urNp coreutils-8.5-orig/src/cut.c coreutils-8.5/src/cut.c struct range_pair { size_t lo; -@@ -89,7 +152,7 @@ static char *field_1_buffer; +@@ -90,7 +153,7 @@ static char *field_1_buffer; /* The number of bytes allocated for FIELD_1_BUFFER. */ static size_t field_1_bufsize; @@ -119,7 +119,7 @@ diff -urNp coreutils-8.5-orig/src/cut.c coreutils-8.5/src/cut.c or degenerate range specification; this doesn't include the starting index of right-open-ended ranges. For example, with either range spec `2-5,9-', `2-3,5,9-' this variable would be set to 5. */ -@@ -101,10 +164,11 @@ static size_t eol_range_start; +@@ -102,10 +165,11 @@ static size_t eol_range_start; /* This is a bit vector. In byte mode, which bytes to output. @@ -133,7 +133,7 @@ diff -urNp coreutils-8.5-orig/src/cut.c coreutils-8.5/src/cut.c (K <= MAX_RANGE_ENDPOINT and is_printable_field(K)) || (EOL_RANGE_START > 0 && K >= EOL_RANGE_START). */ static unsigned char *printable_field; -@@ -113,15 +177,25 @@ enum operating_mode +@@ -114,15 +178,25 @@ enum operating_mode { undefined_mode, @@ -160,7 +160,7 @@ diff -urNp coreutils-8.5-orig/src/cut.c coreutils-8.5/src/cut.c /* If true do not output lines containing no delimeter characters. Otherwise, all such lines are printed. This option is valid only with field mode. */ -@@ -133,6 +207,9 @@ static bool complement; +@@ -134,6 +208,9 @@ static bool complement; /* The delimeter character for field mode. */ static unsigned char delim; @@ -170,7 +170,7 @@ diff -urNp coreutils-8.5-orig/src/cut.c coreutils-8.5/src/cut.c /* True if the --output-delimiter=STRING option was specified. */ static bool output_delimiter_specified; -@@ -206,7 +283,7 @@ Mandatory arguments to long options are +@@ -207,7 +284,7 @@ Mandatory arguments to long options are -f, --fields=LIST select only these fields; also print any line\n\ that contains no delimiter character, unless\n\ the -s option is specified\n\ @@ -179,7 +179,7 @@ diff -urNp coreutils-8.5-orig/src/cut.c coreutils-8.5/src/cut.c "), stdout); fputs (_("\ --complement complement the set of selected bytes, characters\n\ -@@ -365,7 +442,7 @@ set_fields (const char *fieldstr) +@@ -366,7 +443,7 @@ set_fields (const char *fieldstr) in_digits = false; /* Starting a range. */ if (dash_found) @@ -188,7 +188,7 @@ diff -urNp coreutils-8.5-orig/src/cut.c coreutils-8.5/src/cut.c dash_found = true; fieldstr++; -@@ -389,14 +466,16 @@ set_fields (const char *fieldstr) +@@ -390,14 +467,16 @@ set_fields (const char *fieldstr) if (!rhs_specified) { /* `n-'. From `initial' to end of line. */ @@ -207,7 +207,7 @@ diff -urNp coreutils-8.5-orig/src/cut.c coreutils-8.5/src/cut.c /* Is there already a range going to end of line? */ if (eol_range_start != 0) -@@ -476,6 +555,9 @@ set_fields (const char *fieldstr) +@@ -477,6 +556,9 @@ set_fields (const char *fieldstr) if (operating_mode == byte_mode) error (0, 0, _("byte offset %s is too large"), quote (bad_num)); @@ -217,7 +217,7 @@ diff -urNp coreutils-8.5-orig/src/cut.c coreutils-8.5/src/cut.c else error (0, 0, _("field number %s is too large"), quote (bad_num)); -@@ -486,7 +568,7 @@ set_fields (const char *fieldstr) +@@ -487,7 +569,7 @@ set_fields (const char *fieldstr) fieldstr++; } else @@ -226,7 +226,7 @@ diff -urNp coreutils-8.5-orig/src/cut.c coreutils-8.5/src/cut.c } max_range_endpoint = 0; -@@ -579,6 +661,63 @@ cut_bytes (FILE *stream) +@@ -580,6 +662,63 @@ cut_bytes (FILE *stream) } } @@ -290,7 +290,7 @@ diff -urNp coreutils-8.5-orig/src/cut.c coreutils-8.5/src/cut.c /* Read from stream STREAM, printing to standard output any selected fields. */ static void -@@ -701,13 +840,192 @@ cut_fields (FILE *stream) +@@ -702,13 +841,192 @@ cut_fields (FILE *stream) } } @@ -486,16 +486,16 @@ diff -urNp coreutils-8.5-orig/src/cut.c coreutils-8.5/src/cut.c } /* Process file FILE to standard output. -@@ -757,6 +1075,8 @@ main (int argc, char **argv) +@@ -760,6 +1078,8 @@ main (int argc, char **argv) bool ok; bool delim_specified = false; - char *spec_list_string IF_LINT (= NULL); + char *spec_list_string IF_LINT ( = NULL); + char mbdelim[MB_LEN_MAX + 1]; + size_t delimlen = 0; initialize_main (&argc, &argv); set_program_name (argv[0]); -@@ -779,7 +1099,6 @@ main (int argc, char **argv) +@@ -782,7 +1102,6 @@ main (int argc, char **argv) switch (optc) { case 'b': @@ -503,7 +503,7 @@ diff -urNp coreutils-8.5-orig/src/cut.c coreutils-8.5/src/cut.c /* Build the byte list. */ if (operating_mode != undefined_mode) FATAL_ERROR (_("only one type of list may be specified")); -@@ -787,6 +1106,14 @@ main (int argc, char **argv) +@@ -790,6 +1109,14 @@ main (int argc, char **argv) spec_list_string = optarg; break; @@ -518,7 +518,7 @@ diff -urNp coreutils-8.5-orig/src/cut.c coreutils-8.5/src/cut.c case 'f': /* Build the field list. */ if (operating_mode != undefined_mode) -@@ -798,10 +1125,35 @@ main (int argc, char **argv) +@@ -801,10 +1128,35 @@ main (int argc, char **argv) case 'd': /* New delimiter. */ /* Interpret -d '' to mean `use the NUL byte as the delimiter.' */ @@ -558,7 +558,7 @@ diff -urNp coreutils-8.5-orig/src/cut.c coreutils-8.5/src/cut.c break; case OUTPUT_DELIMITER_OPTION: -@@ -814,6 +1166,7 @@ main (int argc, char **argv) +@@ -817,6 +1169,7 @@ main (int argc, char **argv) break; case 'n': @@ -566,7 +566,7 @@ diff -urNp coreutils-8.5-orig/src/cut.c coreutils-8.5/src/cut.c break; case 's': -@@ -836,7 +1189,7 @@ main (int argc, char **argv) +@@ -839,7 +1192,7 @@ main (int argc, char **argv) if (operating_mode == undefined_mode) FATAL_ERROR (_("you must specify a list of bytes, characters, or fields")); @@ -575,7 +575,7 @@ diff -urNp coreutils-8.5-orig/src/cut.c coreutils-8.5/src/cut.c FATAL_ERROR (_("an input delimiter may be specified only\ when operating on fields")); -@@ -863,15 +1216,34 @@ main (int argc, char **argv) +@@ -866,15 +1219,34 @@ main (int argc, char **argv) } if (!delim_specified) @@ -616,10 +616,10 @@ diff -urNp coreutils-8.5-orig/src/cut.c coreutils-8.5/src/cut.c } if (optind == argc) -diff -urNp coreutils-8.5-orig/src/expand.c coreutils-8.5/src/expand.c ---- coreutils-8.5-orig/src/expand.c 2010-01-01 14:06:47.000000000 +0100 -+++ coreutils-8.5/src/expand.c 2010-04-26 14:24:33.000000000 +0200 -@@ -38,11 +38,28 @@ +diff -urNp coreutils-8.7-orig/src/expand.c coreutils-8.7/src/expand.c +--- coreutils-8.7-orig/src/expand.c 2010-10-11 19:35:11.000000000 +0200 ++++ coreutils-8.7/src/expand.c 2010-11-15 09:59:36.977172637 +0100 +@@ -38,12 +38,29 @@ #include #include #include @@ -631,6 +631,7 @@ diff -urNp coreutils-8.5-orig/src/expand.c coreutils-8.5/src/expand.c + #include "system.h" #include "error.h" + #include "fadvise.h" #include "quote.h" #include "xstrndup.h" @@ -648,7 +649,7 @@ diff -urNp coreutils-8.5-orig/src/expand.c coreutils-8.5/src/expand.c /* The official name of this program (e.g., no `g' prefix). */ #define PROGRAM_NAME "expand" -@@ -358,6 +375,142 @@ expand (void) +@@ -360,6 +377,142 @@ expand (void) } } @@ -791,7 +792,7 @@ diff -urNp coreutils-8.5-orig/src/expand.c coreutils-8.5/src/expand.c int main (int argc, char **argv) { -@@ -422,7 +575,12 @@ main (int argc, char **argv) +@@ -424,7 +577,12 @@ main (int argc, char **argv) file_list = (optind < argc ? &argv[optind] : stdin_argv); @@ -805,10 +806,10 @@ diff -urNp coreutils-8.5-orig/src/expand.c coreutils-8.5/src/expand.c if (have_read_stdin && fclose (stdin) != 0) error (EXIT_FAILURE, errno, "-"); -diff -urNp coreutils-8.5-orig/src/fold.c coreutils-8.5/src/fold.c ---- coreutils-8.5-orig/src/fold.c 2010-01-01 14:06:47.000000000 +0100 -+++ coreutils-8.5/src/fold.c 2010-04-26 14:24:33.000000000 +0200 -@@ -22,11 +22,33 @@ +diff -urNp coreutils-8.7-orig/src/fold.c coreutils-8.7/src/fold.c +--- coreutils-8.7-orig/src/fold.c 2010-10-16 13:28:01.000000000 +0200 ++++ coreutils-8.7/src/fold.c 2010-11-15 09:59:36.979181926 +0100 +@@ -22,12 +22,34 @@ #include #include @@ -824,6 +825,7 @@ diff -urNp coreutils-8.5-orig/src/fold.c coreutils-8.5/src/fold.c + #include "system.h" #include "error.h" + #include "fadvise.h" #include "quote.h" #include "xstrtol.h" @@ -842,7 +844,7 @@ diff -urNp coreutils-8.5-orig/src/fold.c coreutils-8.5/src/fold.c #define TAB_WIDTH 8 /* The official name of this program (e.g., no `g' prefix). */ -@@ -34,20 +56,41 @@ +@@ -35,20 +57,41 @@ #define AUTHORS proper_name ("David MacKenzie") @@ -888,7 +890,7 @@ diff -urNp coreutils-8.5-orig/src/fold.c coreutils-8.5/src/fold.c {"spaces", no_argument, NULL, 's'}, {"width", required_argument, NULL, 'w'}, {GETOPT_HELP_OPTION_DECL}, -@@ -77,6 +120,7 @@ Mandatory arguments to long options are +@@ -78,6 +121,7 @@ Mandatory arguments to long options are "), stdout); fputs (_("\ -b, --bytes count bytes rather than columns\n\ @@ -896,7 +898,7 @@ diff -urNp coreutils-8.5-orig/src/fold.c coreutils-8.5/src/fold.c -s, --spaces break at spaces\n\ -w, --width=WIDTH use WIDTH columns instead of 80\n\ "), stdout); -@@ -94,7 +138,7 @@ Mandatory arguments to long options are +@@ -95,7 +139,7 @@ Mandatory arguments to long options are static size_t adjust_column (size_t column, char c) { @@ -905,7 +907,7 @@ diff -urNp coreutils-8.5-orig/src/fold.c coreutils-8.5/src/fold.c { if (c == '\b') { -@@ -117,30 +161,14 @@ adjust_column (size_t column, char c) +@@ -118,30 +162,14 @@ adjust_column (size_t column, char c) to stdout, with maximum line length WIDTH. Return true if successful. */ @@ -936,9 +938,9 @@ diff -urNp coreutils-8.5-orig/src/fold.c coreutils-8.5/src/fold.c - return false; - } - while ((c = getc (istream)) != EOF) - { -@@ -168,6 +196,15 @@ fold_file (char const *filename, size_t + fadvise (istream, FADVISE_SEQUENTIAL); + +@@ -171,6 +199,15 @@ fold_file (char const *filename, size_t bool found_blank = false; size_t logical_end = offset_out; @@ -954,7 +956,7 @@ diff -urNp coreutils-8.5-orig/src/fold.c coreutils-8.5/src/fold.c /* Look for the last blank. */ while (logical_end) { -@@ -214,11 +251,222 @@ fold_file (char const *filename, size_t +@@ -217,11 +254,222 @@ fold_file (char const *filename, size_t line_out[offset_out++] = c; } @@ -1178,7 +1180,7 @@ diff -urNp coreutils-8.5-orig/src/fold.c coreutils-8.5/src/fold.c if (ferror (istream)) { error (0, saved_errno, "%s", filename); -@@ -251,7 +499,8 @@ main (int argc, char **argv) +@@ -254,7 +502,8 @@ main (int argc, char **argv) atexit (close_stdout); @@ -1188,7 +1190,7 @@ diff -urNp coreutils-8.5-orig/src/fold.c coreutils-8.5/src/fold.c while ((optc = getopt_long (argc, argv, shortopts, longopts, NULL)) != -1) { -@@ -260,7 +509,15 @@ main (int argc, char **argv) +@@ -263,7 +512,15 @@ main (int argc, char **argv) switch (optc) { case 'b': /* Count bytes rather than columns. */ @@ -1205,10 +1207,10 @@ diff -urNp coreutils-8.5-orig/src/fold.c coreutils-8.5/src/fold.c break; case 's': /* Break at word boundaries. */ -diff -urNp coreutils-8.5-orig/src/join.c coreutils-8.5/src/join.c ---- coreutils-8.5-orig/src/join.c 2010-04-20 21:52:04.000000000 +0200 -+++ coreutils-8.5/src/join.c 2010-04-26 14:24:33.000000000 +0200 -@@ -22,17 +22,31 @@ +diff -urNp coreutils-8.7-orig/src/join.c coreutils-8.7/src/join.c +--- coreutils-8.7-orig/src/join.c 2010-10-11 19:35:11.000000000 +0200 ++++ coreutils-8.7/src/join.c 2010-11-15 09:59:36.980181716 +0100 +@@ -22,18 +22,32 @@ #include #include @@ -1224,6 +1226,7 @@ diff -urNp coreutils-8.5-orig/src/join.c coreutils-8.5/src/join.c + #include "system.h" #include "error.h" + #include "fadvise.h" #include "hard-locale.h" #include "linebuffer.h" -#include "memcasecmp.h" @@ -1241,7 +1244,7 @@ diff -urNp coreutils-8.5-orig/src/join.c coreutils-8.5/src/join.c /* The official name of this program (e.g., no `g' prefix). */ #define PROGRAM_NAME "join" -@@ -121,10 +135,12 @@ static struct outlist outlist_head; +@@ -122,10 +136,12 @@ static struct outlist outlist_head; /* Last element in `outlist', where a new element can be added. */ static struct outlist *outlist_end = &outlist_head; @@ -1258,11 +1261,11 @@ diff -urNp coreutils-8.5-orig/src/join.c coreutils-8.5/src/join.c /* If nonzero, check that the input is correctly ordered. */ static enum -@@ -248,10 +264,11 @@ xfields (struct line *line) +@@ -249,13 +265,14 @@ xfields (struct line *line) if (ptr == lim) return; -- if (0 <= tab) +- if (0 <= tab && tab != '\n') + if (tab != NULL) { + unsigned char t = tab[0]; @@ -1271,8 +1274,12 @@ diff -urNp coreutils-8.5-orig/src/join.c coreutils-8.5/src/join.c + for (; (sep = memchr (ptr, t, lim - ptr)) != NULL; ptr = sep + 1) extract_field (line, ptr, sep - ptr); } - else -@@ -278,6 +295,148 @@ xfields (struct line *line) +- else if (tab < 0) ++ else + { + /* Skip leading blanks before the first field. */ + while (isblank (to_uchar (*ptr))) +@@ -279,6 +296,148 @@ xfields (struct line *line) extract_field (line, ptr, lim - ptr); } @@ -1421,7 +1428,7 @@ diff -urNp coreutils-8.5-orig/src/join.c coreutils-8.5/src/join.c static void freeline (struct line *line) { -@@ -299,56 +458,115 @@ keycmp (struct line const *line1, struct +@@ -300,56 +459,115 @@ keycmp (struct line const *line1, struct size_t jf_1, size_t jf_2) { /* Start of field to compare in each file. */ @@ -1560,7 +1567,7 @@ diff -urNp coreutils-8.5-orig/src/join.c coreutils-8.5/src/join.c } /* Check that successive input lines PREV and CURRENT from input file -@@ -429,6 +647,11 @@ get_line (FILE *fp, struct line **linep, +@@ -430,6 +648,11 @@ get_line (FILE *fp, struct line **linep, return false; } @@ -1572,7 +1579,7 @@ diff -urNp coreutils-8.5-orig/src/join.c coreutils-8.5/src/join.c xfields (line); if (prevline[which - 1]) -@@ -528,11 +751,18 @@ prfield (size_t n, struct line const *li +@@ -529,11 +752,18 @@ prfield (size_t n, struct line const *li /* Print the join of LINE1 and LINE2. */ @@ -1592,7 +1599,7 @@ diff -urNp coreutils-8.5-orig/src/join.c coreutils-8.5/src/join.c outlist = outlist_head.next; if (outlist) -@@ -567,7 +797,7 @@ prjoin (struct line const *line1, struct +@@ -568,7 +798,7 @@ prjoin (struct line const *line1, struct o = o->next; if (o == NULL) break; @@ -1601,7 +1608,7 @@ diff -urNp coreutils-8.5-orig/src/join.c coreutils-8.5/src/join.c } putchar ('\n'); } -@@ -585,23 +815,23 @@ prjoin (struct line const *line1, struct +@@ -586,23 +816,23 @@ prjoin (struct line const *line1, struct prfield (join_field_1, line1); for (i = 0; i < join_field_1 && i < line1->nfields; ++i) { @@ -1629,7 +1636,7 @@ diff -urNp coreutils-8.5-orig/src/join.c coreutils-8.5/src/join.c prfield (i, line2); } putchar ('\n'); -@@ -1039,21 +1269,46 @@ main (int argc, char **argv) +@@ -1043,21 +1273,46 @@ main (int argc, char **argv) case 't': { @@ -1685,9 +1692,9 @@ diff -urNp coreutils-8.5-orig/src/join.c coreutils-8.5/src/join.c break; case NOCHECK_ORDER_OPTION: -diff -urNp coreutils-8.5-orig/src/pr.c coreutils-8.5/src/pr.c ---- coreutils-8.5-orig/src/pr.c 2010-03-13 16:14:09.000000000 +0100 -+++ coreutils-8.5/src/pr.c 2010-04-26 14:24:33.000000000 +0200 +diff -urNp coreutils-8.7-orig/src/pr.c coreutils-8.7/src/pr.c +--- coreutils-8.7-orig/src/pr.c 2010-10-11 19:35:11.000000000 +0200 ++++ coreutils-8.7/src/pr.c 2010-11-15 09:59:36.983181856 +0100 @@ -312,6 +312,32 @@ #include @@ -1720,8 +1727,8 @@ diff -urNp coreutils-8.5-orig/src/pr.c coreutils-8.5/src/pr.c + #include "system.h" #include "error.h" - #include "hard-locale.h" -@@ -322,6 +348,18 @@ + #include "fadvise.h" +@@ -323,6 +349,18 @@ #include "strftime.h" #include "xstrtol.h" @@ -1740,7 +1747,7 @@ diff -urNp coreutils-8.5-orig/src/pr.c coreutils-8.5/src/pr.c /* The official name of this program (e.g., no `g' prefix). */ #define PROGRAM_NAME "pr" -@@ -414,7 +452,20 @@ struct COLUMN +@@ -415,7 +453,20 @@ struct COLUMN typedef struct COLUMN COLUMN; @@ -1762,7 +1769,7 @@ diff -urNp coreutils-8.5-orig/src/pr.c coreutils-8.5/src/pr.c static bool read_line (COLUMN *p); static bool print_page (void); static bool print_stored (COLUMN *p); -@@ -424,6 +475,7 @@ static void print_header (void); +@@ -425,6 +476,7 @@ static void print_header (void); static void pad_across_to (int position); static void add_line_number (COLUMN *p); static void getoptarg (char *arg, char switch_char, char *character, @@ -1770,7 +1777,7 @@ diff -urNp coreutils-8.5-orig/src/pr.c coreutils-8.5/src/pr.c int *number); void usage (int status); static void print_files (int number_of_files, char **av); -@@ -438,7 +490,6 @@ static void store_char (char c); +@@ -439,7 +491,6 @@ static void store_char (char c); static void pad_down (int lines); static void read_rest_of_line (COLUMN *p); static void skip_read (COLUMN *p, int column_number); @@ -1778,7 +1785,7 @@ diff -urNp coreutils-8.5-orig/src/pr.c coreutils-8.5/src/pr.c static void cleanup (void); static void print_sep_string (void); static void separator_string (const char *optarg_S); -@@ -450,7 +501,7 @@ static COLUMN *column_vector; +@@ -451,7 +502,7 @@ static COLUMN *column_vector; we store the leftmost columns contiguously in buff. To print a line from buff, get the index of the first character from line_vector[i], and print up to line_vector[i + 1]. */ @@ -1787,7 +1794,7 @@ diff -urNp coreutils-8.5-orig/src/pr.c coreutils-8.5/src/pr.c /* Index of the position in buff where the next character will be stored. */ -@@ -554,7 +605,7 @@ static int chars_per_column; +@@ -555,7 +606,7 @@ static int chars_per_column; static bool untabify_input = false; /* (-e) The input tab character. */ @@ -1796,7 +1803,7 @@ diff -urNp coreutils-8.5-orig/src/pr.c coreutils-8.5/src/pr.c /* (-e) Tabstops are at chars_per_tab, 2*chars_per_tab, 3*chars_per_tab, ... where the leftmost column is 1. */ -@@ -564,7 +615,10 @@ static int chars_per_input_tab = 8; +@@ -565,7 +616,10 @@ static int chars_per_input_tab = 8; static bool tabify_output = false; /* (-i) The output tab character. */ @@ -1808,7 +1815,7 @@ diff -urNp coreutils-8.5-orig/src/pr.c coreutils-8.5/src/pr.c /* (-i) The width of the output tab. */ static int chars_per_output_tab = 8; -@@ -638,7 +692,13 @@ static int power_10; +@@ -639,7 +693,13 @@ static int power_10; static bool numbered_lines = false; /* (-n) Character which follows each line number. */ @@ -1823,7 +1830,7 @@ diff -urNp coreutils-8.5-orig/src/pr.c coreutils-8.5/src/pr.c /* (-n) line counting starts with 1st line of input file (not with 1st line of 1st page printed). */ -@@ -691,6 +751,7 @@ static bool use_col_separator = false; +@@ -692,6 +752,7 @@ static bool use_col_separator = false; -a|COLUMN|-m is a `space' and with the -J option a `tab'. */ static char *col_sep_string = (char *) ""; static int col_sep_length = 0; @@ -1831,7 +1838,7 @@ diff -urNp coreutils-8.5-orig/src/pr.c coreutils-8.5/src/pr.c static char *column_separator = (char *) " "; static char *line_separator = (char *) "\t"; -@@ -847,6 +908,13 @@ separator_string (const char *optarg_S) +@@ -848,6 +909,13 @@ separator_string (const char *optarg_S) col_sep_length = (int) strlen (optarg_S); col_sep_string = xmalloc (col_sep_length + 1); strcpy (col_sep_string, optarg_S); @@ -1845,7 +1852,7 @@ diff -urNp coreutils-8.5-orig/src/pr.c coreutils-8.5/src/pr.c } int -@@ -871,6 +939,21 @@ main (int argc, char **argv) +@@ -872,6 +940,21 @@ main (int argc, char **argv) atexit (close_stdout); @@ -1867,7 +1874,7 @@ diff -urNp coreutils-8.5-orig/src/pr.c coreutils-8.5/src/pr.c n_files = 0; file_names = (argc > 1 ? xmalloc ((argc - 1) * sizeof (char *)) -@@ -947,8 +1030,12 @@ main (int argc, char **argv) +@@ -948,8 +1031,12 @@ main (int argc, char **argv) break; case 'e': if (optarg) @@ -1882,7 +1889,7 @@ diff -urNp coreutils-8.5-orig/src/pr.c coreutils-8.5/src/pr.c /* Could check tab width > 0. */ untabify_input = true; break; -@@ -961,8 +1048,12 @@ main (int argc, char **argv) +@@ -962,8 +1049,12 @@ main (int argc, char **argv) break; case 'i': if (optarg) @@ -1897,7 +1904,7 @@ diff -urNp coreutils-8.5-orig/src/pr.c coreutils-8.5/src/pr.c /* Could check tab width > 0. */ tabify_output = true; break; -@@ -989,8 +1080,8 @@ main (int argc, char **argv) +@@ -990,8 +1081,8 @@ main (int argc, char **argv) case 'n': numbered_lines = true; if (optarg) @@ -1908,7 +1915,7 @@ diff -urNp coreutils-8.5-orig/src/pr.c coreutils-8.5/src/pr.c break; case 'N': skip_count = false; -@@ -1029,7 +1120,7 @@ main (int argc, char **argv) +@@ -1030,7 +1121,7 @@ main (int argc, char **argv) old_s = false; /* Reset an additional input of -s, -S dominates -s */ col_sep_string = bad_cast (""); @@ -1917,7 +1924,7 @@ diff -urNp coreutils-8.5-orig/src/pr.c coreutils-8.5/src/pr.c use_col_separator = true; if (optarg) separator_string (optarg); -@@ -1186,10 +1277,45 @@ main (int argc, char **argv) +@@ -1187,10 +1278,45 @@ main (int argc, char **argv) a number. */ static void @@ -1965,7 +1972,7 @@ diff -urNp coreutils-8.5-orig/src/pr.c coreutils-8.5/src/pr.c if (*arg) { long int tmp_long; -@@ -1248,7 +1374,7 @@ init_parameters (int number_of_files) +@@ -1249,7 +1375,7 @@ init_parameters (int number_of_files) else col_sep_string = column_separator; @@ -1974,7 +1981,7 @@ diff -urNp coreutils-8.5-orig/src/pr.c coreutils-8.5/src/pr.c use_col_separator = true; } /* It's rather pointless to define a TAB separator with column -@@ -1279,11 +1405,11 @@ init_parameters (int number_of_files) +@@ -1280,11 +1406,11 @@ init_parameters (int number_of_files) TAB_WIDTH (chars_per_input_tab, chars_per_number); */ /* Estimate chars_per_text without any margin and keep it constant. */ @@ -1988,7 +1995,7 @@ diff -urNp coreutils-8.5-orig/src/pr.c coreutils-8.5/src/pr.c /* The number is part of the column width unless we are printing files in parallel. */ -@@ -1298,7 +1424,7 @@ init_parameters (int number_of_files) +@@ -1299,7 +1425,7 @@ init_parameters (int number_of_files) } chars_per_column = (chars_per_line - chars_used_by_number - @@ -1997,7 +2004,7 @@ diff -urNp coreutils-8.5-orig/src/pr.c coreutils-8.5/src/pr.c if (chars_per_column < 1) error (EXIT_FAILURE, 0, _("page width too narrow")); -@@ -1423,7 +1549,7 @@ init_funcs (void) +@@ -1424,7 +1550,7 @@ init_funcs (void) /* Enlarge p->start_position of first column to use the same form of padding_not_printed with all columns. */ @@ -2006,7 +2013,7 @@ diff -urNp coreutils-8.5-orig/src/pr.c coreutils-8.5/src/pr.c /* This loop takes care of all but the rightmost column. */ -@@ -1457,7 +1583,7 @@ init_funcs (void) +@@ -1458,7 +1584,7 @@ init_funcs (void) } else { @@ -2015,7 +2022,7 @@ diff -urNp coreutils-8.5-orig/src/pr.c coreutils-8.5/src/pr.c h_next = h + chars_per_column; } } -@@ -1747,9 +1873,9 @@ static void +@@ -1749,9 +1875,9 @@ static void align_column (COLUMN *p) { padding_not_printed = p->start_position; @@ -2027,7 +2034,7 @@ diff -urNp coreutils-8.5-orig/src/pr.c coreutils-8.5/src/pr.c padding_not_printed = ANYWHERE; } -@@ -2020,13 +2146,13 @@ store_char (char c) +@@ -2022,13 +2148,13 @@ store_char (char c) /* May be too generous. */ buff = X2REALLOC (buff, &buff_allocated); } @@ -2043,7 +2050,7 @@ diff -urNp coreutils-8.5-orig/src/pr.c coreutils-8.5/src/pr.c char *s; int left_cut; -@@ -2049,22 +2175,24 @@ add_line_number (COLUMN *p) +@@ -2051,22 +2177,24 @@ add_line_number (COLUMN *p) /* Tabification is assumed for multiple columns, also for n-separators, but `default n-separator = TAB' hasn't been given priority over equal column_width also specified by POSIX. */ @@ -2072,7 +2079,7 @@ diff -urNp coreutils-8.5-orig/src/pr.c coreutils-8.5/src/pr.c output_position = POS_AFTER_TAB (chars_per_output_tab, output_position); } -@@ -2225,7 +2353,7 @@ print_white_space (void) +@@ -2227,7 +2355,7 @@ print_white_space (void) while (goal - h_old > 1 && (h_new = POS_AFTER_TAB (chars_per_output_tab, h_old)) <= goal) { @@ -2081,7 +2088,7 @@ diff -urNp coreutils-8.5-orig/src/pr.c coreutils-8.5/src/pr.c h_old = h_new; } while (++h_old <= goal) -@@ -2245,6 +2373,7 @@ print_sep_string (void) +@@ -2247,6 +2375,7 @@ print_sep_string (void) { char *s; int l = col_sep_length; @@ -2089,7 +2096,7 @@ diff -urNp coreutils-8.5-orig/src/pr.c coreutils-8.5/src/pr.c s = col_sep_string; -@@ -2258,6 +2387,7 @@ print_sep_string (void) +@@ -2260,6 +2389,7 @@ print_sep_string (void) { for (; separators_not_printed > 0; --separators_not_printed) { @@ -2097,7 +2104,7 @@ diff -urNp coreutils-8.5-orig/src/pr.c coreutils-8.5/src/pr.c while (l-- > 0) { /* 3 types of sep_strings: spaces only, spaces and chars, -@@ -2271,12 +2401,15 @@ print_sep_string (void) +@@ -2273,12 +2403,15 @@ print_sep_string (void) } else { @@ -2114,7 +2121,7 @@ diff -urNp coreutils-8.5-orig/src/pr.c coreutils-8.5/src/pr.c /* sep_string ends with some spaces */ if (spaces_not_printed > 0) print_white_space (); -@@ -2304,7 +2437,7 @@ print_clump (COLUMN *p, int n, char *clu +@@ -2306,7 +2439,7 @@ print_clump (COLUMN *p, int n, char *clu required number of tabs and spaces. */ static void @@ -2123,7 +2130,7 @@ diff -urNp coreutils-8.5-orig/src/pr.c coreutils-8.5/src/pr.c { if (tabify_output) { -@@ -2328,6 +2461,74 @@ print_char (char c) +@@ -2330,6 +2463,74 @@ print_char (char c) putchar (c); } @@ -2198,7 +2205,7 @@ diff -urNp coreutils-8.5-orig/src/pr.c coreutils-8.5/src/pr.c /* Skip to page PAGE before printing. PAGE may be larger than total number of pages. */ -@@ -2507,9 +2708,9 @@ read_line (COLUMN *p) +@@ -2509,9 +2710,9 @@ read_line (COLUMN *p) align_empty_cols = false; } @@ -2210,7 +2217,7 @@ diff -urNp coreutils-8.5-orig/src/pr.c coreutils-8.5/src/pr.c padding_not_printed = ANYWHERE; } -@@ -2610,9 +2811,9 @@ print_stored (COLUMN *p) +@@ -2612,9 +2813,9 @@ print_stored (COLUMN *p) } } @@ -2222,7 +2229,7 @@ diff -urNp coreutils-8.5-orig/src/pr.c coreutils-8.5/src/pr.c padding_not_printed = ANYWHERE; } -@@ -2625,8 +2826,8 @@ print_stored (COLUMN *p) +@@ -2627,8 +2828,8 @@ print_stored (COLUMN *p) if (spaces_not_printed == 0) { output_position = p->start_position + end_vector[line]; @@ -2233,7 +2240,7 @@ diff -urNp coreutils-8.5-orig/src/pr.c coreutils-8.5/src/pr.c } return true; -@@ -2645,7 +2846,7 @@ print_stored (COLUMN *p) +@@ -2647,7 +2848,7 @@ print_stored (COLUMN *p) number of characters is 1.) */ static int @@ -2242,7 +2249,7 @@ diff -urNp coreutils-8.5-orig/src/pr.c coreutils-8.5/src/pr.c { unsigned char uc = c; char *s = clump_buff; -@@ -2655,10 +2856,10 @@ char_to_clump (char c) +@@ -2657,10 +2858,10 @@ char_to_clump (char c) int chars; int chars_per_c = 8; @@ -2255,7 +2262,7 @@ diff -urNp coreutils-8.5-orig/src/pr.c coreutils-8.5/src/pr.c { width = TAB_WIDTH (chars_per_c, input_position); -@@ -2739,6 +2940,154 @@ char_to_clump (char c) +@@ -2741,6 +2942,154 @@ char_to_clump (char c) return chars; } @@ -2410,15 +2417,16 @@ diff -urNp coreutils-8.5-orig/src/pr.c coreutils-8.5/src/pr.c /* We've just printed some files and need to clean up things before looking for more options and printing the next batch of files. -diff -urNp coreutils-8.5-orig/src/sort.c coreutils-8.5/src/sort.c ---- coreutils-8.5-orig/src/sort.c 2010-04-21 09:06:17.000000000 +0200 -+++ coreutils-8.5/src/sort.c 2010-04-26 14:24:33.000000000 +0200 -@@ -22,10 +22,19 @@ +diff -urNp coreutils-8.7-orig/src/sort.c coreutils-8.7/src/sort.c +--- coreutils-8.7-orig/src/sort.c 2010-10-25 12:07:57.000000000 +0200 ++++ coreutils-8.7/src/sort.c 2010-11-15 09:59:36.987932380 +0100 +@@ -22,11 +22,20 @@ #include +#include #include + #include #include #include #include @@ -2433,12 +2441,8 @@ diff -urNp coreutils-8.5-orig/src/sort.c coreutils-8.5/src/sort.c #include "system.h" #include "argmatch.h" #include "error.h" -@@ -124,14 +133,38 @@ static int decimal_point; - /* Thousands separator; if -1, then there isn't one. */ - static int thousands_sep; +@@ -159,12 +168,34 @@ static int thousands_sep; -+static int force_general_numcompare = 0; -+ /* Nonzero if the corresponding locales are hard. */ static bool hard_LC_COLLATE; -#if HAVE_NL_LANGINFO @@ -2473,7 +2477,7 @@ diff -urNp coreutils-8.5-orig/src/sort.c coreutils-8.5/src/sort.c /* The kind of blanks for '-b' to skip in various options. */ enum blanktype { bl_start, bl_end, bl_both }; -@@ -270,13 +303,11 @@ static bool reverse; +@@ -328,13 +359,11 @@ static bool reverse; they were read if all keys compare equal. */ static bool stable; @@ -2490,7 +2494,7 @@ diff -urNp coreutils-8.5-orig/src/sort.c coreutils-8.5/src/sort.c /* Flag to remove consecutive duplicate lines from the output. Only the last of a sequence of equal lines will be output. */ -@@ -714,6 +745,44 @@ reap_some (void) +@@ -782,6 +811,46 @@ reap_some (void) update_proc (pid); } @@ -2501,8 +2505,10 @@ diff -urNp coreutils-8.5-orig/src/sort.c coreutils-8.5/src/sort.c +(*begfield) (const struct line*, const struct keyfield *); +static char * +(*limfield) (const struct line*, const struct keyfield *); ++static void ++(*skipblanks) (char **ptr, char *lim); +static int -+(*getmonth) (char const *, size_t); ++(*getmonth) (char const *, size_t, char **); +static int +(*keycompare) (const struct line *, const struct line *); +static int @@ -2535,7 +2541,7 @@ diff -urNp coreutils-8.5-orig/src/sort.c coreutils-8.5/src/sort.c /* Clean up any remaining temporary files. */ static void -@@ -1158,7 +1227,7 @@ zaptemp (const char *name) +@@ -1205,7 +1274,7 @@ zaptemp (char const *name) free (node); } @@ -2543,8 +2549,8 @@ diff -urNp coreutils-8.5-orig/src/sort.c coreutils-8.5/src/sort.c +#if HAVE_LANGINFO_CODESET static int - struct_month_cmp (const void *m1, const void *m2) -@@ -1173,7 +1242,7 @@ struct_month_cmp (const void *m1, const + struct_month_cmp (void const *m1, void const *m2) +@@ -1220,7 +1289,7 @@ struct_month_cmp (void const *m1, void c /* Initialize the character class tables. */ static void @@ -2553,7 +2559,7 @@ diff -urNp coreutils-8.5-orig/src/sort.c coreutils-8.5/src/sort.c { size_t i; -@@ -1185,7 +1254,7 @@ inittables (void) +@@ -1232,7 +1301,7 @@ inittables (void) fold_toupper[i] = toupper (i); } @@ -2562,7 +2568,7 @@ diff -urNp coreutils-8.5-orig/src/sort.c coreutils-8.5/src/sort.c /* If we're not in the "C" locale, read different names for months. */ if (hard_LC_TIME) { -@@ -1268,6 +1337,64 @@ specify_nmerge (int oi, char c, char con +@@ -1314,6 +1383,84 @@ specify_nmerge (int oi, char c, char con xstrtol_fatal (e, oi, c, long_options, s); } @@ -2571,12 +2577,25 @@ diff -urNp coreutils-8.5-orig/src/sort.c coreutils-8.5/src/sort.c +inittables_mb (void) +{ + int i, j, k, l; -+ char *name, *s; ++ char *name, *s, *lc_time, *lc_ctype; + size_t s_len, mblength; + char mbc[MB_LEN_MAX]; + wchar_t wc, pwc; + mbstate_t state_mb, state_wc; + ++ lc_time = setlocale (LC_TIME, ""); ++ if (lc_time) ++ lc_time = xstrdup (lc_time); ++ ++ lc_ctype = setlocale (LC_CTYPE, ""); ++ if (lc_ctype) ++ lc_ctype = xstrdup (lc_ctype); ++ ++ if (lc_time && lc_ctype) ++ /* temporarily set LC_CTYPE to match LC_TIME, so that we can convert ++ * the names of months to upper case */ ++ setlocale (LC_CTYPE, lc_time); ++ + for (i = 0; i < MONTHS_PER_YEAR; i++) + { + s = (char *) nl_langinfo (ABMON_1 + i); @@ -2621,22 +2640,29 @@ diff -urNp coreutils-8.5-orig/src/sort.c coreutils-8.5/src/sort.c + } + qsort ((void *) monthtab, MONTHS_PER_YEAR, + sizeof (struct month), struct_month_cmp); ++ ++ if (lc_time && lc_ctype) ++ /* restore the original locales */ ++ setlocale (LC_CTYPE, lc_ctype); ++ ++ free (lc_ctype); ++ free (lc_time); +} +#endif + /* Specify the amount of main memory to use when sorting. */ static void specify_sort_size (int oi, char c, char const *s) -@@ -1478,7 +1605,7 @@ buffer_linelim (struct buffer const *buf +@@ -1540,7 +1687,7 @@ buffer_linelim (struct buffer const *buf by KEY in LINE. */ static char * --begfield (const struct line *line, const struct keyfield *key) +-begfield (struct line const *line, struct keyfield const *key) +begfield_uni (const struct line *line, const struct keyfield *key) { char *ptr = line->text, *lim = ptr + line->length - 1; size_t sword = key->sword; -@@ -1487,10 +1614,10 @@ begfield (const struct line *line, const +@@ -1549,10 +1696,10 @@ begfield (struct line const *line, struc /* The leading field separator itself is included in a field when -t is absent. */ @@ -2649,7 +2675,7 @@ diff -urNp coreutils-8.5-orig/src/sort.c coreutils-8.5/src/sort.c ++ptr; if (ptr < lim) ++ptr; -@@ -1516,11 +1643,70 @@ begfield (const struct line *line, const +@@ -1578,11 +1725,70 @@ begfield (struct line const *line, struc return ptr; } @@ -2716,12 +2742,12 @@ diff -urNp coreutils-8.5-orig/src/sort.c coreutils-8.5/src/sort.c in LINE specified by KEY. */ static char * --limfield (const struct line *line, const struct keyfield *key) +-limfield (struct line const *line, struct keyfield const *key) +limfield_uni (const struct line *line, const struct keyfield *key) { char *ptr = line->text, *lim = ptr + line->length - 1; size_t eword = key->eword, echar = key->echar; -@@ -1535,10 +1721,10 @@ limfield (const struct line *line, const +@@ -1597,10 +1803,10 @@ limfield (struct line const *line, struc `beginning' is the first character following the delimiting TAB. Otherwise, leave PTR pointing at the first `blank' character after the preceding field. */ @@ -2734,7 +2760,7 @@ diff -urNp coreutils-8.5-orig/src/sort.c coreutils-8.5/src/sort.c ++ptr; if (ptr < lim && (eword || echar)) ++ptr; -@@ -1584,10 +1770,10 @@ limfield (const struct line *line, const +@@ -1646,10 +1852,10 @@ limfield (struct line const *line, struc */ /* Make LIM point to the end of (one byte past) the current field. */ @@ -2747,7 +2773,7 @@ diff -urNp coreutils-8.5-orig/src/sort.c coreutils-8.5/src/sort.c if (newlim) lim = newlim; } -@@ -1618,6 +1804,113 @@ limfield (const struct line *line, const +@@ -1680,6 +1886,130 @@ limfield (struct line const *line, struc return ptr; } @@ -2857,11 +2883,28 @@ diff -urNp coreutils-8.5-orig/src/sort.c coreutils-8.5/src/sort.c + return ptr; +} +#endif ++ ++static void ++skipblanks_uni (char **ptr, char *lim) ++{ ++ while (*ptr < lim && blanks[to_uchar (**ptr)]) ++ ++(*ptr); ++} ++ ++#if HAVE_MBRTOWC ++static void ++skipblanks_mb (char **ptr, char *lim) ++{ ++ size_t mblength; ++ while (*ptr < lim && ismbblank (*ptr, lim - *ptr, &mblength)) ++ (*ptr) += mblength; ++} ++#endif + /* Fill BUF reading from FP, moving buf->left bytes from the end of buf->buf to the beginning first. If EOF is reached and the file wasn't terminated by a newline, supply one. Set up BUF's line -@@ -1700,8 +1993,24 @@ fillbuf (struct buffer *buf, FILE *fp, c +@@ -1766,8 +2096,22 @@ fillbuf (struct buffer *buf, FILE *fp, c else { if (key->skipsblanks) @@ -2872,8 +2915,6 @@ diff -urNp coreutils-8.5-orig/src/sort.c coreutils-8.5/src/sort.c + if (MB_CUR_MAX > 1) + { + size_t mblength; -+ mbstate_t state; -+ memset (&state, '\0', sizeof(mbstate_t)); + while (line_start < line->keylim && + ismbblank (line_start, + line->keylim - line_start, @@ -2888,17 +2929,17 @@ diff -urNp coreutils-8.5-orig/src/sort.c coreutils-8.5/src/sort.c line->keybeg = line_start; } } -@@ -1739,7 +2048,7 @@ fillbuf (struct buffer *buf, FILE *fp, c +@@ -1888,7 +2232,7 @@ human_numcompare (char const *a, char co hideously fast. */ static int --numcompare (const char *a, const char *b) +-numcompare (char const *a, char const *b) +numcompare_uni (const char *a, const char *b) { while (blanks[to_uchar (*a)]) a++; -@@ -1848,6 +2157,25 @@ human_numcompare (const char *a, const c - : strnumcmp (a, b, decimal_point, thousands_sep)); +@@ -1898,6 +2242,25 @@ numcompare (char const *a, char const *b + return strnumcmp (a, b, decimal_point, thousands_sep); } +#if HAVE_MBRTOWC @@ -2921,24 +2962,49 @@ diff -urNp coreutils-8.5-orig/src/sort.c coreutils-8.5/src/sort.c +#endif /* HAV_EMBRTOWC */ + static int - general_numcompare (const char *sa, const char *sb) + general_numcompare (char const *sa, char const *sb) { -@@ -1881,7 +2209,7 @@ general_numcompare (const char *sa, cons +@@ -1930,7 +2293,7 @@ general_numcompare (char const *sa, char Return 0 if the name in S is not recognized. */ static int --getmonth (char const *month, size_t len) -+getmonth_uni (char const *month, size_t len) +-getmonth (char const *month, char **ea) ++getmonth_uni (char const *month, size_t len, char **ea) { size_t lo = 0; size_t hi = MONTHS_PER_YEAR; -@@ -2062,11 +2390,79 @@ compare_version (char *restrict texta, s - return diff; +@@ -2204,13 +2567,12 @@ debug_key (struct line const *line, stru + { + char saved = *lim; *lim = '\0'; + +- while (blanks[to_uchar (*beg)]) +- beg++; ++ skipblanks (&beg, lim); + + char *tighter_lim = beg; + + if (key->month) +- getmonth (beg, &tighter_lim); ++ getmonth (beg, lim-beg, &tighter_lim); + else if (key->general_numeric) + ignore_value (strtold (beg, &tighter_lim)); + else if (key->numeric || key->human_numeric) +@@ -2354,7 +2716,7 @@ key_warnings (struct keyfield const *gke + bool maybe_space_aligned = !hard_LC_COLLATE && default_key_compare (key) + && !(key->schar || key->echar); + bool line_offset = key->eword == 0 && key->echar != 0; /* -k1.x,1.y */ +- if (!gkey_only && tab == TAB_DEFAULT && !line_offset ++ if (!gkey_only && !tab_length && !line_offset + && ((!key->skipsblanks && !(implicit_skip || maybe_space_aligned)) + || (!key->skipsblanks && key->schar) + || (!key->skipeblanks && key->echar))) +@@ -2412,11 +2774,83 @@ key_warnings (struct keyfield const *gke + error (0, 0, _("option `-r' only applies to last-resort comparison")); } +#if HAVE_MBRTOWC +static int -+getmonth_mb (const char *s, size_t len) ++getmonth_mb (const char *s, size_t len, char **ea) +{ + char *month; + register size_t i; @@ -2969,7 +3035,8 @@ diff -urNp coreutils-8.5-orig/src/sort.c coreutils-8.5/src/sort.c + memset (&state, '\0', sizeof(mbstate_t)); + + wclength = mbsrtowcs (month_wcs, pp, len + 1, &state); -+ assert (wclength != (size_t)-1 && *pp == NULL); ++ if (wclength == (size_t)-1 || *pp != NULL) ++ error (SORT_FAILURE, 0, _("Invalid multibyte input %s."), quote(s)); + + for (i = 0; i < wclength; i++) + { @@ -2997,6 +3064,9 @@ diff -urNp coreutils-8.5-orig/src/sort.c coreutils-8.5/src/sort.c + } + while (hi - lo > 1); + ++ if (ea) ++ *ea = (char *) month; ++ + result = (!strncmp (month, monthtab[lo].name, strlen (monthtab[lo].name)) + ? monthtab[lo].val : 0); + @@ -3008,12 +3078,21 @@ diff -urNp coreutils-8.5-orig/src/sort.c coreutils-8.5/src/sort.c are no more keys or a difference is found. */ static int --keycompare (const struct line *a, const struct line *b) +-keycompare (struct line const *a, struct line const *b) +keycompare_uni (const struct line *a, const struct line *b) { struct keyfield *key = keylist; -@@ -2246,6 +2642,179 @@ keycompare (const struct line *a, const +@@ -2501,7 +2935,7 @@ keycompare (struct line const *a, struct + else if (key->human_numeric) + diff = human_numcompare (ta, tb); + else if (key->month) +- diff = getmonth (ta, NULL) - getmonth (tb, NULL); ++ diff = getmonth (ta, tlena, NULL) - getmonth (tb, tlenb, NULL); + else if (key->random) + diff = compare_random (ta, tlena, tb, tlenb); + else if (key->version) +@@ -2617,6 +3051,179 @@ keycompare (struct line const *a, struct return key->reverse ? -diff : diff; } @@ -3058,13 +3137,13 @@ diff -urNp coreutils-8.5-orig/src/sort.c coreutils-8.5/src/sort.c + *lima = *limb = '\0'; + diff = (key->numeric ? numcompare (texta, textb) + : key->general_numeric ? general_numcompare (texta, textb) -+ : human_numcompare (texta, textb, key)); ++ : human_numcompare (texta, textb)); + *lima = savea, *limb = saveb; + } + else if (key->version) -+ diff = compare_version (texta, lena, textb, lenb); ++ diff = filevercmp (texta, textb); + else if (key->month) -+ diff = getmonth (texta, lena) - getmonth (textb, lenb); ++ diff = getmonth (texta, lena, NULL) - getmonth (textb, lenb, NULL); + else + { + if (ignore || translate) @@ -3193,7 +3272,7 @@ diff -urNp coreutils-8.5-orig/src/sort.c coreutils-8.5/src/sort.c /* Compare two lines A and B, returning negative, zero, or positive depending on whether A compares less than, equal to, or greater than B. */ -@@ -3244,7 +3813,7 @@ main (int argc, char **argv) +@@ -4006,7 +4613,7 @@ main (int argc, char **argv) initialize_exit_failure (SORT_FAILURE); hard_LC_COLLATE = hard_locale (LC_COLLATE); @@ -3202,7 +3281,7 @@ diff -urNp coreutils-8.5-orig/src/sort.c coreutils-8.5/src/sort.c hard_LC_TIME = hard_locale (LC_TIME); #endif -@@ -3265,6 +3834,27 @@ main (int argc, char **argv) +@@ -4027,6 +4634,29 @@ main (int argc, char **argv) thousands_sep = -1; } @@ -3212,6 +3291,7 @@ diff -urNp coreutils-8.5-orig/src/sort.c coreutils-8.5/src/sort.c + inittables = inittables_mb; + begfield = begfield_mb; + limfield = limfield_mb; ++ skipblanks = skipblanks_mb; + getmonth = getmonth_mb; + keycompare = keycompare_mb; + numcompare = numcompare_mb; @@ -3222,6 +3302,7 @@ diff -urNp coreutils-8.5-orig/src/sort.c coreutils-8.5/src/sort.c + inittables = inittables_uni; + begfield = begfield_uni; + limfield = limfield_uni; ++ skipblanks = skipblanks_uni; + getmonth = getmonth_uni; + keycompare = keycompare_uni; + numcompare = numcompare_uni; @@ -3230,7 +3311,7 @@ diff -urNp coreutils-8.5-orig/src/sort.c coreutils-8.5/src/sort.c have_read_stdin = false; inittables (); -@@ -3536,13 +4126,35 @@ main (int argc, char **argv) +@@ -4297,13 +4927,34 @@ main (int argc, char **argv) case 't': { @@ -3247,7 +3328,6 @@ diff -urNp coreutils-8.5-orig/src/sort.c coreutils-8.5/src/sort.c + { + wchar_t wc; + mbstate_t state; -+ size_t i; + + memset (&state, '\0', sizeof (mbstate_t)); + newtab_length = mbrtowc (&wc, newtab, strnlen (newtab, @@ -3270,7 +3350,7 @@ diff -urNp coreutils-8.5-orig/src/sort.c coreutils-8.5/src/sort.c else { /* Provoke with `sort -txx'. Complain about -@@ -3553,9 +4165,12 @@ main (int argc, char **argv) +@@ -4314,9 +4965,12 @@ main (int argc, char **argv) quote (optarg)); } } @@ -3285,10 +3365,10 @@ diff -urNp coreutils-8.5-orig/src/sort.c coreutils-8.5/src/sort.c } break; -diff -urNp coreutils-8.5-orig/src/unexpand.c coreutils-8.5/src/unexpand.c ---- coreutils-8.5-orig/src/unexpand.c 2010-01-01 14:06:47.000000000 +0100 -+++ coreutils-8.5/src/unexpand.c 2010-04-26 14:24:33.000000000 +0200 -@@ -39,11 +39,28 @@ +diff -urNp coreutils-8.7-orig/src/unexpand.c coreutils-8.7/src/unexpand.c +--- coreutils-8.7-orig/src/unexpand.c 2010-10-11 19:35:11.000000000 +0200 ++++ coreutils-8.7/src/unexpand.c 2010-11-15 09:59:36.989931891 +0100 +@@ -39,12 +39,29 @@ #include #include #include @@ -3300,6 +3380,7 @@ diff -urNp coreutils-8.5-orig/src/unexpand.c coreutils-8.5/src/unexpand.c + #include "system.h" #include "error.h" + #include "fadvise.h" #include "quote.h" #include "xstrndup.h" @@ -3317,7 +3398,7 @@ diff -urNp coreutils-8.5-orig/src/unexpand.c coreutils-8.5/src/unexpand.c /* The official name of this program (e.g., no `g' prefix). */ #define PROGRAM_NAME "unexpand" -@@ -103,6 +120,208 @@ static struct option const longopts[] = +@@ -104,6 +121,208 @@ static struct option const longopts[] = {NULL, 0, NULL, 0} }; @@ -3526,7 +3607,7 @@ diff -urNp coreutils-8.5-orig/src/unexpand.c coreutils-8.5/src/unexpand.c void usage (int status) { -@@ -524,7 +743,12 @@ main (int argc, char **argv) +@@ -526,7 +745,12 @@ main (int argc, char **argv) file_list = (optind < argc ? &argv[optind] : stdin_argv); @@ -3540,9 +3621,9 @@ diff -urNp coreutils-8.5-orig/src/unexpand.c coreutils-8.5/src/unexpand.c if (have_read_stdin && fclose (stdin) != 0) error (EXIT_FAILURE, errno, "-"); -diff -urNp coreutils-8.5-orig/src/uniq.c coreutils-8.5/src/uniq.c ---- coreutils-8.5-orig/src/uniq.c 2010-03-13 16:14:09.000000000 +0100 -+++ coreutils-8.5/src/uniq.c 2010-04-26 14:24:33.000000000 +0200 +diff -urNp coreutils-8.7-orig/src/uniq.c coreutils-8.7/src/uniq.c +--- coreutils-8.7-orig/src/uniq.c 2010-10-11 19:35:11.000000000 +0200 ++++ coreutils-8.7/src/uniq.c 2010-11-15 09:59:36.992922043 +0100 @@ -21,6 +21,16 @@ #include #include @@ -3560,7 +3641,7 @@ diff -urNp coreutils-8.5-orig/src/uniq.c coreutils-8.5/src/uniq.c #include "system.h" #include "argmatch.h" #include "linebuffer.h" -@@ -31,7 +41,19 @@ +@@ -32,7 +42,19 @@ #include "stdio--.h" #include "xmemcoll.h" #include "xstrtol.h" @@ -3581,7 +3662,7 @@ diff -urNp coreutils-8.5-orig/src/uniq.c coreutils-8.5/src/uniq.c /* The official name of this program (e.g., no `g' prefix). */ #define PROGRAM_NAME "uniq" -@@ -107,6 +129,10 @@ static enum delimit_method const delimit +@@ -108,6 +130,10 @@ static enum delimit_method const delimit /* Select whether/how to delimit groups of duplicate lines. */ static enum delimit_method delimit_groups; @@ -3592,7 +3673,7 @@ diff -urNp coreutils-8.5-orig/src/uniq.c coreutils-8.5/src/uniq.c static struct option const longopts[] = { {"count", no_argument, NULL, 'c'}, -@@ -206,7 +232,7 @@ size_opt (char const *opt, char const *m +@@ -207,7 +233,7 @@ size_opt (char const *opt, char const *m return a pointer to the beginning of the line's field to be compared. */ static char * @@ -3601,7 +3682,7 @@ diff -urNp coreutils-8.5-orig/src/uniq.c coreutils-8.5/src/uniq.c { size_t count; char const *lp = line->buffer; -@@ -227,6 +253,83 @@ find_field (struct linebuffer const *lin +@@ -228,6 +254,83 @@ find_field (struct linebuffer const *lin return line->buffer + i; } @@ -3685,7 +3766,7 @@ diff -urNp coreutils-8.5-orig/src/uniq.c coreutils-8.5/src/uniq.c /* Return false if two strings OLD and NEW match, true if not. OLD and NEW point not to the beginnings of the lines but rather to the beginnings of the fields to compare. -@@ -235,6 +338,8 @@ find_field (struct linebuffer const *lin +@@ -236,6 +339,8 @@ find_field (struct linebuffer const *lin static bool different (char *old, char *new, size_t oldlen, size_t newlen) { @@ -3694,7 +3775,7 @@ diff -urNp coreutils-8.5-orig/src/uniq.c coreutils-8.5/src/uniq.c if (check_chars < oldlen) oldlen = check_chars; if (check_chars < newlen) -@@ -242,14 +347,92 @@ different (char *old, char *new, size_t +@@ -243,14 +348,92 @@ different (char *old, char *new, size_t if (ignore_case) { @@ -3792,10 +3873,10 @@ diff -urNp coreutils-8.5-orig/src/uniq.c coreutils-8.5/src/uniq.c /* Output the line in linebuffer LINE to standard output provided that the switches say it should be output. -@@ -303,15 +486,43 @@ check_file (const char *infile, const ch +@@ -306,15 +489,43 @@ check_file (const char *infile, const ch { - char *prevfield IF_LINT (= NULL); - size_t prevlen IF_LINT (= 0); + char *prevfield IF_LINT ( = NULL); + size_t prevlen IF_LINT ( = 0); +#if HAVE_MBRTOWC + mbstate_t prevstate; + @@ -3836,7 +3917,7 @@ diff -urNp coreutils-8.5-orig/src/uniq.c coreutils-8.5/src/uniq.c if (prevline->length == 0 || different (thisfield, prevfield, thislen, prevlen)) { -@@ -330,17 +541,26 @@ check_file (const char *infile, const ch +@@ -333,17 +544,26 @@ check_file (const char *infile, const ch size_t prevlen; uintmax_t match_count = 0; bool first_delimiter = true; @@ -3863,7 +3944,7 @@ diff -urNp coreutils-8.5-orig/src/uniq.c coreutils-8.5/src/uniq.c if (readlinebuffer_delim (thisline, stdin, delimiter) == 0) { if (ferror (stdin)) -@@ -349,6 +569,15 @@ check_file (const char *infile, const ch +@@ -352,6 +572,15 @@ check_file (const char *infile, const ch } thisfield = find_field (thisline); thislen = thisline->length - 1 - (thisfield - thisline->buffer); @@ -3879,7 +3960,7 @@ diff -urNp coreutils-8.5-orig/src/uniq.c coreutils-8.5/src/uniq.c match = !different (thisfield, prevfield, thislen, prevlen); match_count += match; -@@ -381,6 +610,9 @@ check_file (const char *infile, const ch +@@ -384,6 +613,9 @@ check_file (const char *infile, const ch SWAP_LINES (prevline, thisline); prevfield = thisfield; prevlen = thislen; @@ -3889,7 +3970,7 @@ diff -urNp coreutils-8.5-orig/src/uniq.c coreutils-8.5/src/uniq.c if (!match) match_count = 0; } -@@ -426,6 +658,19 @@ main (int argc, char **argv) +@@ -429,6 +661,19 @@ main (int argc, char **argv) atexit (close_stdout); @@ -3909,18 +3990,18 @@ diff -urNp coreutils-8.5-orig/src/uniq.c coreutils-8.5/src/uniq.c skip_chars = 0; skip_fields = 0; check_chars = SIZE_MAX; -diff -urNp coreutils-8.5-orig/tests/Makefile.am coreutils-8.5/tests/Makefile.am ---- coreutils-8.5-orig/tests/Makefile.am 2010-04-26 14:24:10.000000000 +0200 -+++ coreutils-8.5/tests/Makefile.am 2010-04-26 14:24:33.000000000 +0200 -@@ -224,6 +224,7 @@ TESTS = \ - misc/sort-compress \ - misc/sort-continue \ +diff -urNp coreutils-8.7-orig/tests/Makefile.am coreutils-8.7/tests/Makefile.am +--- coreutils-8.7-orig/tests/Makefile.am 2010-11-15 09:58:44.197937898 +0100 ++++ coreutils-8.7/tests/Makefile.am 2010-11-15 09:59:36.993932170 +0100 +@@ -231,6 +231,7 @@ TESTS = \ + misc/sort-debug-keys \ + misc/sort-debug-warn \ misc/sort-files0-from \ + misc/sort-mb-tests \ + misc/sort-float \ misc/sort-merge \ misc/sort-merge-fdlimit \ - misc/sort-month \ -@@ -475,6 +476,10 @@ TESTS = \ +@@ -490,6 +491,10 @@ TESTS = \ $(root_tests) pr_data = \ @@ -3931,9 +4012,9 @@ diff -urNp coreutils-8.5-orig/tests/Makefile.am coreutils-8.5/tests/Makefile.am pr/0F \ pr/0FF \ pr/0FFnt \ -diff -urNp coreutils-8.5-orig/tests/misc/cut coreutils-8.5/tests/misc/cut ---- coreutils-8.5-orig/tests/misc/cut 2010-01-01 14:06:47.000000000 +0100 -+++ coreutils-8.5/tests/misc/cut 2010-04-26 14:24:33.000000000 +0200 +diff -urNp coreutils-8.7-orig/tests/misc/cut coreutils-8.7/tests/misc/cut +--- coreutils-8.7-orig/tests/misc/cut 2010-10-11 19:35:11.000000000 +0200 ++++ coreutils-8.7/tests/misc/cut 2010-11-15 09:59:36.994932100 +0100 @@ -26,7 +26,7 @@ use strict; my $prog = 'cut'; my $try = "Try \`$prog --help' for more information.\n"; @@ -3952,41 +4033,41 @@ diff -urNp coreutils-8.5-orig/tests/misc/cut coreutils-8.5/tests/misc/cut ['inval2', qw(-f -), {IN=>''}, {OUT=>''}, {EXIT=>1}, {ERR=>$no_endpoint}], ['inval3', '-f', '4,-', {IN=>''}, {OUT=>''}, {EXIT=>1}, {ERR=>$no_endpoint}], ['inval4', '-f', '1-2,-', {IN=>''}, {OUT=>''}, {EXIT=>1}, {ERR=>$no_endpoint}], -diff -urNp coreutils-8.5-orig/tests/misc/mb1.I coreutils-8.5/tests/misc/mb1.I ---- coreutils-8.5-orig/tests/misc/mb1.I 1970-01-01 01:00:00.000000000 +0100 -+++ coreutils-8.5/tests/misc/mb1.I 2010-04-26 14:24:33.000000000 +0200 +diff -urNp coreutils-8.7-orig/tests/misc/mb1.I coreutils-8.7/tests/misc/mb1.I +--- coreutils-8.7-orig/tests/misc/mb1.I 1970-01-01 01:00:00.000000000 +0100 ++++ coreutils-8.7/tests/misc/mb1.I 2010-11-15 09:59:36.995931961 +0100 @@ -0,0 +1,4 @@ +Apple@10 +Banana@5 +Citrus@20 +Cherry@30 -diff -urNp coreutils-8.5-orig/tests/misc/mb1.X coreutils-8.5/tests/misc/mb1.X ---- coreutils-8.5-orig/tests/misc/mb1.X 1970-01-01 01:00:00.000000000 +0100 -+++ coreutils-8.5/tests/misc/mb1.X 2010-04-26 14:24:33.000000000 +0200 +diff -urNp coreutils-8.7-orig/tests/misc/mb1.X coreutils-8.7/tests/misc/mb1.X +--- coreutils-8.7-orig/tests/misc/mb1.X 1970-01-01 01:00:00.000000000 +0100 ++++ coreutils-8.7/tests/misc/mb1.X 2010-11-15 09:59:36.995931961 +0100 @@ -0,0 +1,4 @@ +Banana@5 +Apple@10 +Citrus@20 +Cherry@30 -diff -urNp coreutils-8.5-orig/tests/misc/mb2.I coreutils-8.5/tests/misc/mb2.I ---- coreutils-8.5-orig/tests/misc/mb2.I 1970-01-01 01:00:00.000000000 +0100 -+++ coreutils-8.5/tests/misc/mb2.I 2010-04-26 14:24:33.000000000 +0200 +diff -urNp coreutils-8.7-orig/tests/misc/mb2.I coreutils-8.7/tests/misc/mb2.I +--- coreutils-8.7-orig/tests/misc/mb2.I 1970-01-01 01:00:00.000000000 +0100 ++++ coreutils-8.7/tests/misc/mb2.I 2010-11-15 09:59:36.996933777 +0100 @@ -0,0 +1,4 @@ +Apple@AA10@@20 +Banana@AA5@@30 +Citrus@AA20@@5 +Cherry@AA30@@10 -diff -urNp coreutils-8.5-orig/tests/misc/mb2.X coreutils-8.5/tests/misc/mb2.X ---- coreutils-8.5-orig/tests/misc/mb2.X 1970-01-01 01:00:00.000000000 +0100 -+++ coreutils-8.5/tests/misc/mb2.X 2010-04-26 14:24:33.000000000 +0200 +diff -urNp coreutils-8.7-orig/tests/misc/mb2.X coreutils-8.7/tests/misc/mb2.X +--- coreutils-8.7-orig/tests/misc/mb2.X 1970-01-01 01:00:00.000000000 +0100 ++++ coreutils-8.7/tests/misc/mb2.X 2010-11-15 09:59:36.997922462 +0100 @@ -0,0 +1,4 @@ +Citrus@AA20@@5 +Cherry@AA30@@10 +Apple@AA10@@20 +Banana@AA5@@30 -diff -urNp coreutils-8.5-orig/tests/misc/sort-mb-tests coreutils-8.5/tests/misc/sort-mb-tests ---- coreutils-8.5-orig/tests/misc/sort-mb-tests 1970-01-01 01:00:00.000000000 +0100 -+++ coreutils-8.5/tests/misc/sort-mb-tests 2010-04-26 14:24:33.000000000 +0200 +diff -urNp coreutils-8.7-orig/tests/misc/sort-mb-tests coreutils-8.7/tests/misc/sort-mb-tests +--- coreutils-8.7-orig/tests/misc/sort-mb-tests 1970-01-01 01:00:00.000000000 +0100 ++++ coreutils-8.7/tests/misc/sort-mb-tests 2010-11-15 09:59:36.997922462 +0100 @@ -0,0 +1,58 @@ +#! /bin/sh +case $# in