diff --git a/Makefile b/Makefile index cc24773ba..bc1da52e6 100644 --- a/Makefile +++ b/Makefile @@ -3,13 +3,15 @@ ENABLE_LTO ?= n ENABLE_STRIP ?= n # Binaries -RUSTC ?= rustc -CARGO ?= cargo -RM := rm +RUSTC ?= rustc +CARGO ?= cargo +CC ?= gcc +RM := rm # Install directories -PREFIX ?= /usr/local -BINDIR ?= /bin +PREFIX ?= /usr/local +BINDIR ?= /bin +LIBDIR ?= /lib # This won't support any directory with spaces in its name, but you can just # make a symlink without spaces that points to the directory. @@ -75,7 +77,6 @@ PROGS := \ seq \ shuf \ sort \ - stdbuf \ sum \ sync \ tac \ @@ -106,6 +107,7 @@ UNIX_PROGS := \ mkfifo \ nice \ nohup \ + stdbuf \ timeout \ tty \ uname \ @@ -137,6 +139,22 @@ INSTALL ?= $(EXES) INSTALLEES := \ $(filter $(INSTALL),$(filter-out $(DONT_INSTALL),$(EXES) uutils)) +# Shared library extension +SYSTEM := $(shell uname) +DYLIB_EXT := +ifeq ($(SYSTEM),Linux) + DYLIB_EXT := so +endif +ifeq ($(SYSTEM),Darwin) + DYLIB_EXT := dylib +endif + +# Libaries to install +LIBS := +ifneq (,$(findstring stdbuf, $(INSTALLEES))) +LIBS += libstdbuf.$(DYLIB_EXT) +endif + # Programs with usable tests TEST_PROGS := \ cat \ @@ -225,6 +243,16 @@ $(BUILDDIR)/uutils: $(SRCDIR)/uutils/uutils.rs $(BUILDDIR)/mkuutils $(RLIB_PATHS $(BUILDDIR)/mkuutils $(BUILDDIR)/gen/uutils.rs $(EXES) $(RUSTC) $(RUSTCBINFLAGS) --extern test=$(BUILDDIR)/libtest.rlib --emit link,dep-info $(BUILDDIR)/gen/uutils.rs --out-dir $(BUILDDIR) $(if $(ENABLE_STRIP),strip $@) + +# Library for stdbuf +$(BUILDIR)/libstdbuf.$(DYLIB_EXT): $(SRCDIR)/stdbuf/libstdbuf.rs $(SRCDIR)/stdbuf/libstdbuf.c $(SRCDIR)/stdbuf/libstdbuf.h | $(BUILDDIR) + cd $(SRCDIR)/stdbuf && \ + $(RUSTC) libstdbuf.rs && \ + $(CC) -c -Wall -Werror -fpic libstdbuf.c -L. -llibstdbuf.a && \ + $(CC) -shared -o libstdbuf.$(DYLIB_EXT) -Wl,--whole-archive liblibstdbuf.a -Wl,--no-whole-archive libstdbuf.o -lpthread && \ + mv *.so $(BUILDDIR) && $(RM) *.o && $(RM) *.a + +$(BUILDDIR)/stdbuf: $(BUILDIR)/libstdbuf.$(DYLIB_EXT) # Dependencies $(BUILDDIR)/.rust-crypto: | $(BUILDDIR) @@ -278,6 +306,10 @@ install: $(addprefix $(BUILDDIR)/,$(INSTALLEES)) for prog in $(INSTALLEES); do \ install $(BUILDDIR)/$$prog $(DESTDIR)$(PREFIX)$(BINDIR)/$(PROG_PREFIX)$$prog; \ done + mkdir -p $(DESTDIR)$(PREFIX)$(LIBDIR) + for lib in $(LIBS); do \ + install $(BUILDDIR)/$$lib $(DESTDIR)$(PREFIX)$(LIBDIR)/$$lib; \ + done # TODO: figure out if there is way for prefixes to work with the symlinks install-multicall: $(BUILDDIR)/uutils @@ -290,6 +322,7 @@ install-multicall: $(BUILDDIR)/uutils uninstall: rm -f $(addprefix $(DESTDIR)$(PREFIX)$(BINDIR)/$(PROG_PREFIX),$(PROGS)) + rm -f $(addprefix $(DESTDIR)$(PREFIX)$(LIBDIR)/,$(LIBS)) uninstall-multicall: rm -f $(addprefix $(DESTDIR)$(PREFIX)$(BINDIR)/,$(PROGS) $(PROG_PREFIX)uutils) diff --git a/src/stdbuf/libstdbuf.rs b/src/stdbuf/libstdbuf.rs index f10775bb1..4c14fab0f 100644 --- a/src/stdbuf/libstdbuf.rs +++ b/src/stdbuf/libstdbuf.rs @@ -1,6 +1,6 @@ #![crate_name = "libstdbuf"] #![crate_type = "staticlib"] -#![feature(macro_rules)] +#![allow(unstable)] extern crate libc; use libc::{c_int, size_t, c_char, FILE, _IOFBF, _IONBF, _IOLBF, setvbuf}; @@ -8,6 +8,7 @@ use std::ptr; use std::os; #[path = "../common/util.rs"] +#[macro_use] mod util; extern { @@ -23,7 +24,7 @@ fn set_buffer(stream: *mut FILE, value: &str) { "0" => (_IONBF, 0 as size_t), "L" => (_IOLBF, 0 as size_t), input => { - let buff_size: uint = match from_str(input) { + let buff_size: usize = match input.parse() { Some(num) => num, None => crash!(1, "incorrect size of buffer!") }; diff --git a/src/stdbuf/prepare_libs.sh b/src/stdbuf/prepare_libs.sh deleted file mode 100755 index 6be6d920d..000000000 --- a/src/stdbuf/prepare_libs.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash - -cd $(dirname $0) -rustc libstdbuf.rs -gcc -c -Wall -Werror -fpic libstdbuf.c -L. -llibstdbuf.a -gcc -shared -o libstdbuf.so -Wl,--whole-archive liblibstdbuf.a -Wl,--no-whole-archive libstdbuf.o -lpthread -mv *.so ../../build/ -rm *.o -rm *.a diff --git a/src/stdbuf/stdbuf.rs b/src/stdbuf/stdbuf.rs index e01a8c60f..3c7f8e8aa 100644 --- a/src/stdbuf/stdbuf.rs +++ b/src/stdbuf/stdbuf.rs @@ -1,4 +1,5 @@ #![crate_name = "stdbuf"] +#![allow(unstable)] /* * This file is part of the uutils coreutils package. @@ -8,22 +9,23 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -#![feature(macro_rules)] extern crate getopts; extern crate libc; use getopts::{optopt, optflag, getopts, usage, Matches, OptGroup}; use std::io::process::{Command, StdioContainer}; +use std::io::fs::PathExtensions; use std::iter::range_inclusive; use std::num::Int; use std::os; #[path = "../common/util.rs"] +#[macro_use] mod util; static NAME: &'static str = "stdbuf"; static VERSION: &'static str = "1.0.0"; -static LIBSTDBUF: &'static str = "libstdbuf.so"; +static LIBSTDBUF: &'static str = "libstdbuf"; enum BufferType { Default, @@ -49,17 +51,17 @@ enum OkMsg { } #[cfg(target_os = "linux")] -fn preload_env() -> &'static str { - "LD_PRELOAD" +fn preload_strings() -> (&'static str, &'static str) { + ("LD_PRELOAD", ".so") } #[cfg(target_os = "macos")] -fn preload_env() -> &'static str { - "DYLD_INSERT_LIBRARIES" +fn preload_strings() -> (&'static str, &'static str) { + ("DYLD_INSERT_LIBRARIES", ".dyl") } #[cfg(not(any(target_os = "linux", target_os = "macos")))] -fn preload_env() -> &'static str { +fn preload_strings() -> (&'static str, &'static str) { crash!(1, "Command not supported for this operating system!") } @@ -88,18 +90,18 @@ fn print_usage(opts: &[OptGroup]) { } fn parse_size(size: &str) -> Option { - let ext = size.trim_left_chars(|c: char| c.is_digit(10)); - let num = size.trim_right_chars(|c: char| c.is_alphabetic()); + let ext = size.trim_left_matches(|&: c: char| c.is_digit(10)); + let num = size.trim_right_matches(|&: c: char| c.is_alphabetic()); let mut recovered = num.to_string(); recovered.push_str(ext); if recovered.as_slice() != size { return None; } - let buf_size: u64 = match from_str(num) { + let buf_size: u64 = match num.parse() { Some(m) => m, None => return None, }; - let (power, base): (uint, u64) = match ext { + let (power, base): (usize, u64) = match ext { "" => (0, 0), "KB" => (1, 1024), "K" => (1, 1000), @@ -182,8 +184,28 @@ fn set_command_env(command: &mut Command, buffer_name: &str, buffer_type: Buffer } } +fn get_preload_env() -> (String, String) { + let (preload, extension) = preload_strings(); + let mut libstdbuf = LIBSTDBUF.to_string(); + libstdbuf.push_str(extension); + // First search for library in directory of executable. + let mut path = match os::self_exe_path() { + Some(exe_path) => exe_path, + None => crash!(1, "Impossible to fetch the path of this executable.") + }; + path.push(libstdbuf.as_slice()); + if path.exists() { + match path.as_str() { + Some(s) => { return (preload.to_string(), s.to_string()); }, + None => crash!(1, "Error while converting path.") + }; + } + // We assume library is in LD_LIBRARY_PATH/ DYLD_LIBRARY_PATH. + (preload.to_string(), libstdbuf) +} -pub fn uumain(args: Vec) -> int { + +pub fn uumain(args: Vec) -> isize { let optgrps = [ optopt("i", "input", "adjust standard input stream buffering", "MODE"), optopt("o", "output", "adjust standard output stream buffering", "MODE"), @@ -216,16 +238,8 @@ pub fn uumain(args: Vec) -> int { } let ref command_name = args[command_idx]; let mut command = Command::new(command_name); - let mut path = match os::self_exe_path() { - Some(exe_path) => exe_path, - None => crash!(1, "Impossible to fetch the path of this executable.") - }; - path.push(LIBSTDBUF); - let libstdbuf = match path.as_str() { - Some(s) => s, - None => crash!(1, "Error while converting path.") - }; - command.args(args.slice_from(command_idx+1)).env(preload_env(), libstdbuf); + let (preload_env, libstdbuf) = get_preload_env(); + command.args(args.slice_from(command_idx+1)).env(preload_env.as_slice(), libstdbuf.as_slice()); command.stdin(StdioContainer::InheritFd(0)).stdout(StdioContainer::InheritFd(1)).stderr(StdioContainer::InheritFd(2)); set_command_env(&mut command, "_STDBUF_I", options.stdin); set_command_env(&mut command, "_STDBUF_O", options.stdout);