summaryrefslogtreecommitdiffstats
path: root/eval.c
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2016-02-12 15:48:29 -0500
committerTavian Barnes <tavianator@tavianator.com>2016-02-12 15:48:55 -0500
commit746962d7368da4df30b4f51403c383d487ef94d2 (patch)
tree1aa8dd1008d0285f1b7d73dadcccd3dcf46ee143 /eval.c
parent5eba5cb9215edff62e2bd7070bb690913cdae7c7 (diff)
downloadbfs-746962d7368da4df30b4f51403c383d487ef94d2.tar.xz
Check the number of open FDs at the start.
This fixes the issues with things like $ bfs -empty 3</dev/null
Diffstat (limited to 'eval.c')
-rw-r--r--eval.c64
1 files changed, 42 insertions, 22 deletions
diff --git a/eval.c b/eval.c
index f08bab5..9beb2f3 100644
--- a/eval.c
+++ b/eval.c
@@ -400,27 +400,6 @@ bool eval_comma(const struct expr *expr, struct eval_state *state) {
}
/**
- * Infer the number of open file descriptors we're allowed to have.
- */
-static int infer_nopenfd() {
- int ret = 4096;
-
- struct rlimit rl;
- if (getrlimit(RLIMIT_NOFILE, &rl) == 0) {
- if (rl.rlim_cur != RLIM_INFINITY) {
- ret = rl.rlim_cur;
- }
- }
-
- // Account for std{in,out,err}, and allow one free for the predicates
- if (ret > 4) {
- ret -= 4;
- }
-
- return ret;
-}
-
-/**
* Type passed as the argument to the bftw() callback.
*/
struct callback_args {
@@ -473,10 +452,51 @@ static enum bftw_action cmdline_callback(struct BFTW *ftwbuf, void *ptr) {
}
/**
+ * Infer the number of open file descriptors we're allowed to have.
+ */
+static int infer_fdlimit() {
+ int ret = 4096;
+
+ struct rlimit rl;
+ if (getrlimit(RLIMIT_NOFILE, &rl) == 0) {
+ if (rl.rlim_cur != RLIM_INFINITY) {
+ ret = rl.rlim_cur;
+ }
+ }
+
+ // Account for std{in,out,err}, and allow an extra fd for the predicates
+ int nopen = 4;
+
+ // Check /dev/fd for the current number of open fds, if possible (we may
+ // have inherited more than just the standard ones)
+ DIR *dir = opendir("/dev/fd");
+ if (dir) {
+ nopen = 0;
+
+ struct dirent *de;
+ while ((de = readdir(dir)) != NULL) {
+ if (strcmp(de->d_name, ".") != 0 && strcmp(de->d_name, "..") != 0) {
+ ++nopen;
+ }
+ }
+
+ closedir(dir);
+ }
+
+ if (ret > nopen) {
+ ret -= nopen;
+ } else {
+ ret = 1;
+ }
+
+ return ret;
+}
+
+/**
* Evaluate the command line.
*/
int eval_cmdline(const struct cmdline *cmdline) {
- int nopenfd = infer_nopenfd();
+ int nopenfd = infer_fdlimit();
struct callback_args args = {
.cmdline = cmdline,