aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2026-04-01 00:56:53 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2026-04-01 00:56:53 +0000
commitc867dad6b9ad48f85cf1ca9182ac4d55c2d1acf7 (patch)
tree6030e710db987746bbea594ed05cbeea4d8ae026
parentaa270d5e3ed791f77f6ceda9cee15276c6a1692f (diff)
downloadexecline-c867dad6b9ad48f85cf1ca9182ac4d55c2d1acf7.tar.gz
Add -v option to redirfd
-rw-r--r--doc/redirfd.html18
-rw-r--r--package/deps-build4
-rw-r--r--package/deps.mak4
-rw-r--r--src/execline/deps-exe/redirfd1
-rw-r--r--src/execline/redirfd.c122
5 files changed, 102 insertions, 47 deletions
diff --git a/doc/redirfd.html b/doc/redirfd.html
index 9dbe409..17b7303 100644
--- a/doc/redirfd.html
+++ b/doc/redirfd.html
@@ -26,7 +26,8 @@ executes a program.
<h2> Interface </h2>
<pre>
- redirfd [ -r | -w | -u | -a | -x ] [ -n ] [ -b ] <em>fd</em> <em>file</em> <em>prog...</em>
+ redirfd [ -r | -w | -u | -a | -x ] [ -n ] [ -b ] <em>fd</em> <em>file</em> <em>prog...</em><br>
+ redirfd [ -r | -w | -u | -a | -x ] [ -n ] [ -b ] [ -v ] [ -e | -E ] <em>var</em> <em>file</em> <em>prog...</em><br>
</pre>
<p>
@@ -34,6 +35,13 @@ executes a program.
to <em>file</em>, then execs into <em>prog...</em>.
</p>
+<p>
+When run with the <tt>-v</tt> option, the first argument is instead
+interpreted as an environment variable. <tt>redirfd</tt> opens <em>file</em>,
+stores the obtained file descriptor into environment variable <em>var</em>,
+then execs into <em>prog...</em>.
+</p>
+
<h2> Options </h2>
<p>
@@ -51,6 +59,14 @@ the -n and -b options may be added in any case.
<li> <tt>-b</tt>&nbsp;: change mode of <em>file</em> after opening it:
to non-blocking mode if the <tt>-n</tt> option was not given,
to blocking mode if it was. </li>
+ <li> <tt>-v</tt>&nbsp;: interpret the first argument as an environment variable,
+and stores the new file descriptor into that variable before execing. </li>
+ <li> <tt>-e</tt>&nbsp;: no autoimport. This is the default. </li>
+ <li> <tt>-E</tt>&nbsp;: autoimport. This is only useful with the <tt>-v</tt> option.
+Instead of executing
+<em>prog...</em>, execute <tt>importas -uSi <em>var</em> <em>prog...</em></tt>.
+This substitutes <em>var</em> into the command line instead of putting it into
+the environment. </li>
</ul>
<h2> Notes </h2>
diff --git a/package/deps-build b/package/deps-build
index 9f5db2d..6381375 100644
--- a/package/deps-build
+++ b/package/deps-build
@@ -1,2 +1,2 @@
-true true /package/prog/skalibs 2.14.5.0 libskarnet
-$usensss false /package/admin/nsss 0.2.1.1 libnsss
+true true /package/prog/skalibs 2.15.0.0 libskarnet
+$usensss false /package/admin/nsss 0.2.1.2 libnsss
diff --git a/package/deps.mak b/package/deps.mak
index a1ef3ab..44338fd 100644
--- a/package/deps.mak
+++ b/package/deps.mak
@@ -45,7 +45,7 @@ src/execline/pipeline.o src/execline/pipeline.lo: src/execline/pipeline.c src/in
src/execline/piperw.o src/execline/piperw.lo: src/execline/piperw.c
src/execline/posix-cd.o src/execline/posix-cd.lo: src/execline/posix-cd.c
src/execline/posix-umask.o src/execline/posix-umask.lo: src/execline/posix-umask.c
-src/execline/redirfd.o src/execline/redirfd.lo: src/execline/redirfd.c
+src/execline/redirfd.o src/execline/redirfd.lo: src/execline/redirfd.c src/include/execline/execline.h
src/execline/runblock.o src/execline/runblock.lo: src/execline/runblock.c src/include/execline/execline.h
src/execline/shift.o src/execline/shift.lo: src/execline/shift.c src/include/execline/execline.h
src/execline/trap.o src/execline/trap.lo: src/execline/trap.c src/include/execline/execline.h
@@ -170,7 +170,7 @@ posix-cd: src/execline/posix-cd.o -lskarnet
posix-umask: EXTRA_LIBS :=
posix-umask: src/execline/posix-umask.o -lskarnet
redirfd: EXTRA_LIBS :=
-redirfd: src/execline/redirfd.o -lskarnet
+redirfd: src/execline/redirfd.o ${LIBEXECLINE} -lskarnet
runblock: EXTRA_LIBS :=
runblock: src/execline/runblock.o ${LIBEXECLINE} -lskarnet
shift: EXTRA_LIBS :=
diff --git a/src/execline/deps-exe/redirfd b/src/execline/deps-exe/redirfd
index e7187fe..97021b5 100644
--- a/src/execline/deps-exe/redirfd
+++ b/src/execline/deps-exe/redirfd
@@ -1 +1,2 @@
+${LIBEXECLINE}
-lskarnet
diff --git a/src/execline/redirfd.c b/src/execline/redirfd.c
index 4dc829d..e7f491b 100644
--- a/src/execline/redirfd.c
+++ b/src/execline/redirfd.c
@@ -3,64 +3,102 @@
#include <fcntl.h>
#include <errno.h>
-#include <skalibs/sgetopt.h>
+#include <skalibs/uint64.h>
#include <skalibs/types.h>
-#include <skalibs/strerr.h>
#include <skalibs/djbunix.h>
-#include <skalibs/exec.h>
+#include <skalibs/envexec.h>
-#define USAGE "redirfd -[ r | w | u | a | x ] [ -n ] [ -b ] fd file prog..."
+#include <execline/execline.h>
+
+#define USAGE "redirfd -[ r | w | u | a | x ] [ -N | -n ] [ -b ] [ -v ] [ -E | -e ] fd file prog..."
#define dieusage() strerr_dieusage(100, USAGE)
+enum golb_e
+{
+ GOLB_READ = 0x0001,
+ GOLB_WRITE = 0x0002,
+ GOLB_CREAT = 0x0004,
+ GOLB_APPEND = 0x0008,
+ GOLB_TRUNC = 0x0010,
+ GOLB_EXCL = 0x0020,
+ GOLB_NONBLOCK = 0x0040,
+ GOLB_CHANGEMODE = 0x0100,
+ GOLB_VAR = 0x0200,
+ GOLB_AUTOIMPORT = 0x0400,
+} ;
+
int main (int argc, char const *const *argv)
{
- int fd, fd2 ;
- unsigned int flags = 0 ;
- int what = -1 ;
- int changemode = 0 ;
- PROG = "redirfd" ;
+ static gol_bool const rgolb[] =
{
- subgetopt l = SUBGETOPT_ZERO ;
- for (;;)
- {
- int opt = subgetopt_r(argc, argv, "rwuaxnb", &l) ;
- if (opt == -1) break ;
- switch (opt)
- {
- case 'r' : what = O_RDONLY ; flags &= ~(O_APPEND|O_CREAT|O_TRUNC|O_EXCL) ; break ;
- case 'w' : what = O_WRONLY ; flags |= O_CREAT|O_TRUNC ; flags &= ~(O_APPEND|O_EXCL) ; break ;
- case 'u' : what = O_RDWR ; flags &= ~(O_APPEND|O_CREAT|O_TRUNC|O_EXCL) ; break ;
- case 'a' : what = O_WRONLY ; flags |= O_CREAT|O_APPEND ; flags &= ~(O_TRUNC|O_EXCL) ; break ;
- case 'x' : what = O_WRONLY ; flags |= O_CREAT|O_EXCL ; flags &= ~(O_APPEND|O_TRUNC) ; break ;
- case 'n' : flags |= O_NONBLOCK ; break ;
- case 'b' : changemode = 1 ; break ;
- default : dieusage() ;
- }
- }
- argc -= l.ind ; argv += l.ind ;
- }
- if ((argc < 3) || (what == -1)) dieusage() ;
- if (!uint0_scan(argv[0], (unsigned int *)&fd)) dieusage() ;
- flags |= what ;
- fd2 = open3(argv[1], flags, 0666) ;
- if ((fd2 == -1) && (what == O_WRONLY) && (errno == ENXIO))
+ { .so = 'r', .lo = 0, .clear = GOLB_WRITE | GOLB_APPEND | GOLB_CREAT | GOLB_TRUNC | GOLB_EXCL, .set = GOLB_READ },
+ { .so = 'w', .lo = 0, .clear = GOLB_READ | GOLB_APPEND | GOLB_EXCL, .set = GOLB_WRITE | GOLB_CREAT | GOLB_TRUNC },
+ { .so = 'u', .lo = 0, .clear = GOLB_APPEND | GOLB_CREAT | GOLB_TRUNC | GOLB_EXCL, .set = GOLB_READ | GOLB_WRITE },
+ { .so = 'a', .lo = 0, .clear = GOLB_READ | GOLB_TRUNC | GOLB_EXCL, .set = GOLB_WRITE | GOLB_CREAT | GOLB_APPEND },
+ { .so = 'x', .lo = 0, .clear = GOLB_READ | GOLB_APPEND | GOLB_TRUNC, .set = GOLB_WRITE | GOLB_CREAT | GOLB_EXCL },
+ { .so = 'N', .lo = "block", .clear = GOLB_NONBLOCK, .set = 0 },
+ { .so = 'n', .lo = "nonblock", .clear = 0, .set = GOLB_NONBLOCK },
+ { .so = 'b', .lo = "switch-block", .clear = 0, .set = GOLB_CHANGEMODE },
+ { .so = 'v', .lo = "variable", .clear = 0, .set = GOLB_VAR },
+ { .so = 'e', .lo = "no-autoimport", .clear = GOLB_AUTOIMPORT, .set = 0 },
+ { .so = 'E', .lo = "autoimport", .clear = 0, .set = GOLB_AUTOIMPORT },
+ { .so = 0, .lo = "no-read", .clear = GOLB_READ, .set = 0 },
+ { .so = 0, .lo = "read", .clear = 0, .set = GOLB_READ },
+ { .so = 0, .lo = "no-write", .clear = GOLB_WRITE, .set = 0 },
+ { .so = 0, .lo = "write", .clear = 0, .set = GOLB_WRITE },
+ { .so = 0, .lo = "no-create", .clear = GOLB_CREAT, .set = 0 },
+ { .so = 0, .lo = "create", .clear = 0, .set = GOLB_CREAT },
+ { .so = 0, .lo = "no-append", .clear = GOLB_APPEND, .set = 0 },
+ { .so = 0, .lo = "append", .clear = 0, .set = GOLB_APPEND },
+ { .so = 0, .lo = "no-trunc", .clear = GOLB_TRUNC, .set = 0 },
+ { .so = 0, .lo = "trunc", .clear = 0, .set = GOLB_TRUNC },
+ { .so = 0, .lo = "no-excl", .clear = GOLB_EXCL, .set = 0 },
+ { .so = 0, .lo = "excl", .clear = 0, .set = GOLB_EXCL },
+ } ;
+ uint64_t wgolb = 0 ;
+ unsigned int golc ;
+ int fd ;
+ unsigned int fdto ;
+ unsigned int flags ;
+ PROG = "redirfd" ;
+
+ golc = gol_main(argc, argv, rgolb, sizeof(rgolb)/sizeof(gol_bool), 0, 0, &wgolb, 0) ;
+ argc -= golc ; argv += golc ;
+ if (argc < 3) dieusage() ;
+ if (!(wgolb & (GOLB_READ | GOLB_WRITE))) dieusage() ;
+ if (!(wgolb & GOLB_VAR))
+ if (!uint0_scan(argv[0], &fdto)) dieusage() ;
+
+ flags =
+ (wgolb & GOLB_WRITE ? wgolb & GOLB_READ ? O_RDWR : O_WRONLY : O_RDONLY) |
+ (wgolb & GOLB_CREAT ? O_CREAT : 0) |
+ (wgolb & GOLB_APPEND ? O_APPEND : 0) |
+ (wgolb & GOLB_TRUNC ? O_TRUNC : 0) |
+ (wgolb & GOLB_EXCL ? O_EXCL : 0) |
+ (wgolb & GOLB_NONBLOCK ? O_NONBLOCK : 0) ;
+
+ fd = open3(argv[1], flags, 0666) ;
+ if (fd == -1 && wgolb & GOLB_WRITE && errno == ENXIO)
{
int fdr = open_read(argv[1]) ;
if (fdr == -1) strerr_diefu2sys(111, "open_read ", argv[1]) ;
- fd2 = open3(argv[1], flags, 0666) ;
+ fd = open3(argv[1], flags, 0666) ;
fd_close(fdr) ;
}
- if (fd2 == -1) strerr_diefu2sys(111, "open ", argv[1]) ;
- if (fd_move(fd, fd2) == -1)
+ if (fd == -1) strerr_diefu2sys(111, "open ", argv[1]) ;
+
+ if (wgolb & GOLB_CHANGEMODE)
+ if ((wgolb & GOLB_NONBLOCK ? ndelay_off(fd) : ndelay_on(fd)) == -1)
+ strerr_diefu1sys(111, "change blocking mode") ;
+ if (wgolb & GOLB_VAR)
{
char fmt[UINT_FMT] ;
- fmt[uint_fmt(fmt, fd2)] = 0 ;
- strerr_diefu4sys(111, "move fd ", fmt, " to fd ", argv[0]) ;
+ fmt[uint_fmt(fmt, fd)] = 0 ;
+ el_modif_and_exec(argv+2, argv[0], fmt, !!(wgolb & GOLB_AUTOIMPORT)) ;
}
- if (changemode)
+ else
{
- if (((flags & O_NONBLOCK) ? ndelay_off(fd) : ndelay_on(fd)) < 0)
- strerr_diefu1sys(111, "change blocking mode") ;
+ if (fd_move(fdto, fd) == -1) strerr_diefu1sys(111, "fd_move") ;
+ xexec(argv+2) ;
}
- xexec(argv+2) ;
}