Skip to content

Commit

Permalink
Merge branch 'release/v0.2.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
gmarcais committed Jun 2, 2023
2 parents 25004fd + 5ca5edf commit 245a72d
Show file tree
Hide file tree
Showing 27 changed files with 372 additions and 29,818 deletions.
10 changes: 10 additions & 0 deletions .github/workflows/c-cpp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: ConorMacBride/install-package@v1
with:
apt: libgtest-dev strace
- uses: actions/checkout@v3
- name: autoconf
run: autoreconf -fi
Expand All @@ -23,3 +26,10 @@ jobs:
run: make check
- name: make distcheck
run: make distcheck
- name: Archive testing logs
if: '!cancelled()'
uses: actions/upload-artifact@v3
with:
name: gtest-logs
path: '**/*.log'
retention-days: 1
15 changes: 15 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,16 @@
.tup
build-*
*~
*.in
*.m4
*.cache
compile
compile_commands.json
config.guess
config.sub
configure
depcomp
install-sh
ltmain.sh
missing
test-driver
6 changes: 3 additions & 3 deletions INSTALL
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
Installation Instructions
*************************

Copyright (C) 1994-1996, 1999-2002, 2004-2016 Free Software
Foundation, Inc.
Copyright (C) 1994-1996, 1999-2002, 2004-2017, 2020-2021 Free
Software Foundation, Inc.

Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
Expand Down Expand Up @@ -225,7 +225,7 @@ order to use an ANSI C compiler:

and if that doesn't work, install pre-built binaries of GCC for HP-UX.

HP-UX 'make' updates targets which have the same time stamps as their
HP-UX 'make' updates targets which have the same timestamps as their
prerequisites, which makes it generally unusable when shipped generated
files such as 'configure' are involved. Use GNU 'make' instead.

Expand Down
4 changes: 4 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
SUBDIRS = . tests
ACLOCAL_AMFLAGS = -I m4

AM_CPPFLAGS = -Wall -I$(top_srcdir)/include
AM_CXXFLAGS = -O3
LDADD = libnoshell.la

# Build library
lib_LTLIBRARIES = libnoshell.la
Expand All @@ -18,3 +20,5 @@ dist_sub_HEADERS = $(INCDIR)/noshell.hpp $(INCDIR)/handle.hpp \
# Install pc file
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = noshell.pc


14 changes: 9 additions & 5 deletions configure.ac
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
AC_INIT([noshell], [0.1.0], [gmarcais@umd.edu])
AC_INIT([noshell],[0.2.0],[gmarcais@cmu.edu])
AC_CANONICAL_HOST
AC_CONFIG_MACRO_DIR([m4])
AM_INIT_AUTOMAKE([subdir-objects])
AM_INIT_AUTOMAKE([subdir-objects foreign parallel-tests color-tests])
AM_SILENT_RULES([yes])
AC_CONFIG_SRCDIR([lib])
AC_CONFIG_HEADERS([config.h])
AC_PROG_LIBTOOL
LT_INIT

# Change default compilation flags
CXXFLAGS="-std=c++0x $CXXFLAGS"
# CXXFLAGS="-std=c++0x $CXXFLAGS"
AC_LANG(C++)
AC_PROG_CXX

AC_CONFIG_FILES([Makefile noshell.pc])
# Find gtest
PKG_CHECK_MODULES([GTEST], [gtest])
PKG_CHECK_MODULES([GTESTMAIN], [gtest_main])

AC_CONFIG_FILES([Makefile tests/Makefile noshell.pc])
AC_OUTPUT
19 changes: 19 additions & 0 deletions doc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,25 @@ noshell::Exit e = "cat"_C("large_file") | "head"_C(1);
e.success(true); // Most likely will return true
```
## Building pipeline incrementally
The redirection operators modify the existing Pipeline object.
To create a pipeline incrementally, directly apply the operator without reassigning the object.
For example, here is an example chaining 10 `cat` commands.
``` cpp
noshell::ostream os;
auto pipeline = os | NS::C("cat");
for(int j = 0; j < 9; ++j)
pipeline | NS::C("cat");
pipeline > "output_file.txt";
NS::Exit e = pipeline.run();
os << "NOOP * 10\n";
os.close();
e.wait();
```
## No literals <a name="No literals"></a>
All the examples in this page make use of the user defined literal
Expand Down
23 changes: 21 additions & 2 deletions include/noshell/handle.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef __NOSHELL_HANDLE_H__
#define __NOSHELL_HANDLE_H__

#include <forward_list>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
Expand Down Expand Up @@ -75,7 +76,7 @@ struct Handle {
(ignore_sigpipe && status().signaled() && status().term_sig() == SIGPIPE));
}

Handle& set_error(error_types et) { asm("int3"); error = et; return *this; }
Handle& set_error(error_types et) { error = et; return *this; }
Handle&& return_error(error_types et) { return std::move(set_error(et)); }
Handle& set_status(int st) { error = STATUS; data.status.value = st; return *this; }
Handle&& return_status(int st) { return std::move(set_status(st)); }
Expand All @@ -92,15 +93,23 @@ struct Handle {
void wait();
};

std::ostream& operator<<(std::ostream& os, const Handle& handle);

class PipeLine;
class Failures {
const std::vector<Handle>& handles;

class iterator : public std::iterator<std::forward_iterator_tag, Handle> {
class iterator {
typedef std::vector<Handle>::const_iterator handle_iterator;
handle_iterator it;
const std::vector<Handle>& handles;
public:
typedef std::forward_iterator_tag iterator_category;
typedef Handle value_type;
typedef Handle* pointer;
typedef Handle& reference;
typedef ptrdiff_t difference_type;

iterator(const std::vector<Handle>& h) : it(h.cbegin()), handles(h) { }
iterator(const std::vector<Handle>& h, handle_iterator i) : it(i), handles(h) { }
// iterator(const handle_iterator i) : it(i) { }
Expand Down Expand Up @@ -142,6 +151,16 @@ class Exit {
void push_handle(Handle&& h) { handles.push_back(std::move(h)); }
void wait() { for(auto& h : handles) h.wait(); }
};

std::ostream& operator<<(std::ostream& os, const Exit& exit) {
auto it = exit.begin();
if(it != exit.end()) {
os << *it;
for(++it; it != exit.end(); ++it)
os << '|' << *it;
}
return os;
}
} // namespace noshell

#endif /* __NOSHELL_HANDLE_H__ */
25 changes: 24 additions & 1 deletion include/noshell/noshell.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <vector>
#include <forward_list>
#include <set>
#include <memory>
#include <initializer_list>

#include <noshell/setters.hpp>
Expand All @@ -18,6 +19,7 @@ typedef std::forward_list<std::unique_ptr<process_setter> > setter_list_type;
class Command {
std::vector<std::string> cmd;
setter_list_type setters;
setup_list_type setups;
public:
std::set<int> redirected; // Set of redirected file descriptors

Expand All @@ -27,6 +29,7 @@ class Command {
Command(Command&& rhs) noexcept
: cmd(std::move(rhs.cmd))
, setters(std::move(rhs.setters))
, setups(std::move(rhs.setups))
, redirected(std::move(rhs.redirected))
{ }
explicit Command(std::vector<std::string>&& c) : cmd(std::move(c)) { }
Expand All @@ -35,6 +38,7 @@ class Command {
Command(std::initializer_list<std::string> l) : cmd(l) { }

void push_setter(process_setter* setter);
void push_setup(process_setup* setup);

Handle run(process_setup* setup = nullptr);
Handle run_wait();
Expand Down Expand Up @@ -65,6 +69,10 @@ class PipeLine {
friend PipeLine& operator>>(PipeLine& pl, from_to_path&& ft);
friend PipeLine& operator<(PipeLine& pl, from_to_fd&& ft);
friend PipeLine& operator<(PipeLine& pl, from_to_path&& ft);
template<typename F>
PipeLine& operator()(F&& fun) &; // Add setup operation
template<typename F>
PipeLine&& operator()(F&& fun) &&;
};

// Structure to create pipeline object. Works with arbitrary number of
Expand Down Expand Up @@ -170,9 +178,11 @@ inline PipeLine&& operator>(PipeLine&& pl, std::string& path) { return std::move

PipeLine& operator>>(PipeLine& pl, from_to_path&& path);
inline PipeLine&& operator>>(PipeLine&& pl, const char* path) { return std::move(pl >> from_to_path(1, path)); }
inline PipeLine& operator>>(PipeLine& pl, const char* path) { return pl >> from_to_path(1, path); }
inline PipeLine& operator>>(PipeLine& pl, const std::string& path) { return pl >> path.c_str(); }
inline PipeLine& operator>>(PipeLine& pl, std::string&& path) { return pl >> from_to_path(1, std::move(path)); }
inline PipeLine&& operator>>(PipeLine&& pl, const std::string& path) { return std::move(pl >> std::move(path)); }
inline PipeLine&& operator>>(PipeLine&& pl, const std::string& path) { return std::move(pl >> path.c_str()); }
inline PipeLine&& operator>>(PipeLine&& pl, const std::string&& path) { return std::move(pl >> std::move(path)); }

PipeLine& operator<(PipeLine& cmd, const from_to_fd&& ft);
inline PipeLine&& operator<(PipeLine&& cmd, from_to_fd&& ft) { return std::move(cmd < std::move(ft)); }
Expand All @@ -181,6 +191,7 @@ inline PipeLine&& operator<(PipeLine&& cmd, int fd) { return std::move(cmd < fd)

PipeLine& operator<(PipeLine& pl, from_to_path&& ft);
inline PipeLine&& operator<(PipeLine&& pl, from_to_path&& ft) { return std::move(pl < std::move(ft)); }
inline PipeLine& operator<(PipeLine& pl, const char* path) { return pl < from_to_path(0, path); }
inline PipeLine&& operator<(PipeLine&& pl, const char* path) { return std::move(pl < from_to_path(0, path)); }
inline PipeLine& operator<(PipeLine& pl, const std::string& path) { return pl < path.c_str(); }
inline PipeLine&& operator<(PipeLine&& pl, const std::string& path) { return std::move(pl < path.c_str()); }
Expand Down Expand Up @@ -219,6 +230,18 @@ template<typename T>
inline PipeLine& operator|(T& x, PipeLine& pl) { return from_to_ref<T>(0, x) | pl; }
template<typename T>
inline PipeLine&& operator|(T& x, PipeLine&& pl) { return std::move(x | pl); }

template<typename F>
PipeLine& PipeLine::operator()(F&& fun) & {
commands.back().push_setup(new user_process_setup<F>(std::forward<F>(fun)));
return *this;
}
template<typename F>
PipeLine&& PipeLine::operator()(F&& fun) && {
commands.back().push_setup(new user_process_setup<F>(std::forward<F>(fun)));
return std::move(*this);
}

} // namespace noshell

#endif /* __NOSHELL_NOSHELL_H__ */
10 changes: 8 additions & 2 deletions include/noshell/setters.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,7 @@ struct pipeline_redirection : public process_setup {
std::copy(p0, p0 + 2, pipe0);
std::copy(p1, p1 + 2, pipe1);
}
virtual ~pipeline_redirection();
virtual bool child_setup();
virtual bool parent_setup(std::string& err);
virtual bool fix_collisions(const std::set<int>& r) {
return fix_collision(pipe0[0], r) && fix_collision(pipe0[1], r) && fix_collision(pipe1[0], r) && fix_collision(pipe1[1], r);
}
Expand Down Expand Up @@ -230,6 +228,14 @@ struct stream_pipe_redirection_setter : public fd_pipe_redirection_setter {
};
#endif // defined(__GLIBCXX__) || defined(HAVE_STDIO_FILEBUF_H)

// User process setup
template<typename F>
struct user_process_setup : public process_setup {
F fun;
user_process_setup(F f) : fun(f) { }
virtual bool child_setup() { return fun(); }
};

// Traits to select the proper setter
template<typename T>
struct setter_traits { };
Expand Down
18 changes: 18 additions & 0 deletions include/noshell/utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,23 @@ struct auto_close {
~auto_close() { safe_close(fd); }
};

// Handle pipe fds
struct auto_pipe_close {
int fds[2];
auto_pipe_close() : fds{-1, -1} {}
auto_pipe_close(int is[2]) : fds{is[0], is[1]} {}
~auto_pipe_close() { close(); }
void close() {
safe_close(fds[0]);
safe_close(fds[1]);
}
auto_pipe_close& operator=(int is[2]) {
close();
fds[0] = is[0];
fds[1] = is[1];
return *this;
}
};

} // namespace noshell
#endif /* __NOSHELL_UTILS_H__ */
Loading

0 comments on commit 245a72d

Please sign in to comment.