summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2015-08-14 23:29:04 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2015-08-14 23:29:04 +0000
commitd0996a25bd4030875fbc98cabea815dd6741dd0d (patch)
tree49295e4681122292d33a6a4362390e912e771a25 /src
parent9212da01bbaa900dbff8aca9b07b92d821251df2 (diff)
downloadexecline-d0996a25bd4030875fbc98cabea815dd6741dd0d.tar.xz
Add withstdinas
Diffstat (limited to 'src')
-rw-r--r--src/execline/backtick.c125
-rw-r--r--src/execline/deps-exe/backtick1
-rw-r--r--src/execline/deps-exe/withstdinas1
-rw-r--r--src/execline/forbacktickx.c2
-rw-r--r--src/execline/withstdinas.c93
5 files changed, 153 insertions, 69 deletions
diff --git a/src/execline/backtick.c b/src/execline/backtick.c
index 844882b..41b95d6 100644
--- a/src/execline/backtick.c
+++ b/src/execline/backtick.c
@@ -1,92 +1,83 @@
/* ISC license. */
-#include <sys/types.h>
-#include <sys/wait.h>
#include <unistd.h>
-#include <skalibs/bytestr.h>
+#include <errno.h>
+#include <skalibs/uint.h>
#include <skalibs/sgetopt.h>
#include <skalibs/strerr2.h>
-#include <skalibs/stralloc.h>
#include <skalibs/djbunix.h>
+#include <execline/config.h>
#include <execline/execline.h>
-#define USAGE "backtick [ -i | -D default ] [ -n ] var { prog... } remainder..."
+#define USAGE "backtick [ -i | -D default ] [ -n ] var { prog... } command..."
#define dieusage() strerr_dieusage(100, USAGE)
-int main (int argc, char const **argv, char const *const *envp)
+int main (int argc, char const *const *argv, char const *const *envp)
{
- subgetopt_t localopt = SUBGETOPT_ZERO ;
- pid_t pid ;
- int argc1, fdwstat ;
- stralloc modif = STRALLOC_ZERO ;
- unsigned int modifstart ;
- int insist = 0, chomp = 0 ;
char const *def = 0 ;
+ int insist = 0, chomp = 0 ;
PROG = "backtick" ;
- for (;;)
{
- register int opt = subgetopt_r(argc, argv, "einD:", &localopt) ;
- if (opt < 0) break ;
- switch (opt)
+ subgetopt_t l = SUBGETOPT_ZERO ;
+ for (;;)
{
- case 'i' : insist = 1 ; break ;
- case 'n' : chomp = 1 ; break ;
- case 'e' : break ; /* compat */
- case 'D' : def = localopt.arg ; break ;
- default : dieusage() ;
+ register int opt = subgetopt_r(argc, argv, "eniD:", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'e' : break ; /* compat */
+ case 'n' : chomp = 1 ; break ;
+ case 'i' : insist = 1 ; break ;
+ case 'D' : def = l.arg ; break ;
+ default : dieusage() ;
+ }
}
+ argc -= l.ind ; argv += l.ind ;
}
- argc -= localopt.ind ; argv += localopt.ind ;
-
if (argc < 2) dieusage() ;
- if (!*argv[0]) strerr_dief1x(100, "empty variable not accepted") ;
- if (!stralloc_cats(&modif, argv[0]) || !stralloc_catb(&modif, "=", 1))
- strerr_diefu1sys(111, "stralloc_catb") ;
- modifstart = modif.len ;
- argc-- ; argv++ ;
- argc1 = el_semicolon(argv) ;
- if (!argc1) strerr_dief1x(100, "empty block") ;
- if (argc1 >= argc) strerr_dief1x(100, "unterminated block") ;
-
- argv[argc1] = 0 ;
- pid = child_spawn1_pipe(argv[0], argv, envp, &fdwstat, 1) ;
- if (!pid) strerr_diefu2sys(111, "spawn ", argv[0]) ;
- if (!slurp(&modif, fdwstat)) strerr_diefu1sys(111, "slurp") ;
- close(fdwstat) ;
- if (wait_pid(pid, &fdwstat) < 0) strerr_diefu1sys(111, "wait_pid") ;
-
- if (wait_status(fdwstat))
+ if (!argv[0][0]) dieusage() ;
+ if (!argv[1][0]) strerr_dief1x(100, "empty block") ;
{
- if (insist)
- if (WIFSIGNALED(fdwstat)) strerr_dief1x(111, "child process crashed") ;
- else strerr_dief1x(WEXITSTATUS(fdwstat), "child process exited non-zero") ;
- else if (def)
+ unsigned int m = 0, i = 1 ;
+ int fd = dup(0) ;
+ char const *newargv[argc + 15] ;
+ char fmt[UINT_FMT] ;
+ if (fd < 0)
{
- modif.len = modifstart ;
- if (!stralloc_cats(&modif, def)) strerr_diefu1sys(111, "stralloc_catb") ;
+ if (errno != EBADF) strerr_diefu1sys(111, "dup stdin") ;
}
- }
- if (argc == argc1 - 1) return 0 ;
- if (!stralloc_0(&modif)) strerr_diefu1sys(111, "stralloc_catb") ;
- {
- unsigned int reallen = str_len(modif.s) ;
- if (reallen < modif.len - 1)
+ else fmt[uint_fmt(fmt, (unsigned int)fd)] = 0 ;
+ newargv[m++] = EXECLINE_BINPREFIX "pipeline" ;
+ newargv[m++] = "--" ;
+ while (argv[i] && argv[i][0] != EXECLINE_BLOCK_END_CHAR && (!EXECLINE_BLOCK_END_CHAR || (argv[i][0] && argv[i][1])))
+ newargv[m++] = argv[i++] ;
+ if (!argv[i]) strerr_dief1x(100, "unterminated block") ;
+ newargv[m++] = "" ; i++ ;
+ newargv[m++] = EXECLINE_BINPREFIX "withstdinas" ;
+ if (insist) newargv[m++] = "-i" ;
+ if (chomp) newargv[m++] = "-n" ;
+ if (def)
{
- if (insist)
- strerr_dief1x(1, "child process output contained a null character") ;
- else if (def)
- {
- modif.len = modifstart ;
- if (!stralloc_catb(&modif, def, str_len(def)+1))
- strerr_diefu1sys(111, "stralloc_catb") ;
- strerr_warnw2x("child process output contained a null character", " - using default instead") ;
- }
- else
- modif.len = reallen + 1 ;
+ newargv[m++] = "-D" ;
+ newargv[m++] = def ;
+ }
+ newargv[m++] = "-!" ;
+ newargv[m++] = "--" ;
+ newargv[m++] = argv[0] ;
+ if (fd < 0)
+ {
+ newargv[m++] = EXECLINE_BINPREFIX "fdclose" ;
+ newargv[m++] = "0" ;
+ }
+ else
+ {
+ newargv[m++] = EXECLINE_BINPREFIX "fdmove" ;
+ newargv[m++] = "0" ;
+ newargv[m++] = fmt ;
}
- if (chomp && (modif.s[modif.len - 2] == '\n'))
- modif.s[--modif.len - 1] = 0 ;
+ while (argv[i]) newargv[m++] = argv[i++] ;
+ newargv[m++] = 0 ;
+ pathexec_run(newargv[0], newargv, envp) ;
+ strerr_dieexec(111, newargv[0]) ;
}
- pathexec_r(argv + argc1 + 1, envp, env_len(envp), modif.s, modif.len) ;
- strerr_dieexec(111, argv[argc1 + 1]) ;
}
diff --git a/src/execline/deps-exe/backtick b/src/execline/deps-exe/backtick
index 97021b5..e7187fe 100644
--- a/src/execline/deps-exe/backtick
+++ b/src/execline/deps-exe/backtick
@@ -1,2 +1 @@
-${LIBEXECLINE}
-lskarnet
diff --git a/src/execline/deps-exe/withstdinas b/src/execline/deps-exe/withstdinas
new file mode 100644
index 0000000..e7187fe
--- /dev/null
+++ b/src/execline/deps-exe/withstdinas
@@ -0,0 +1 @@
+-lskarnet
diff --git a/src/execline/forbacktickx.c b/src/execline/forbacktickx.c
index 9301581..c0c617a 100644
--- a/src/execline/forbacktickx.c
+++ b/src/execline/forbacktickx.c
@@ -16,7 +16,7 @@
#define DELIM_DEFAULT " \n\r\t"
-int main (int argc, char const **argv, char const *const *envp)
+int main (int argc, char const *const *argv, char const *const *envp)
{
char const *delim = DELIM_DEFAULT ;
char const *codes = 0 ;
diff --git a/src/execline/withstdinas.c b/src/execline/withstdinas.c
new file mode 100644
index 0000000..c1e3c36
--- /dev/null
+++ b/src/execline/withstdinas.c
@@ -0,0 +1,93 @@
+/* ISC license. */
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <string.h>
+#include <skalibs/uint64.h>
+#include <skalibs/bytestr.h>
+#include <skalibs/sgetopt.h>
+#include <skalibs/strerr2.h>
+#include <skalibs/stralloc.h>
+#include <skalibs/djbunix.h>
+
+#define USAGE "withstdinas [ -i | -D default ] [ -n ] var remainder..."
+#define dieusage() strerr_dieusage(100, USAGE)
+
+int main (int argc, char const **argv, char const *const *envp)
+{
+ subgetopt_t localopt = SUBGETOPT_ZERO ;
+ stralloc modif = STRALLOC_ZERO ;
+ unsigned int modifstart ;
+ int insist = 0, chomp = 0, reapit = 0 ;
+ char const *def = 0 ;
+ PROG = "withstdinas" ;
+ for (;;)
+ {
+ register int opt = subgetopt_r(argc, argv, "einD:!", &localopt) ;
+ if (opt < 0) break ;
+ switch (opt)
+ {
+ case 'i' : insist = 1 ; break ;
+ case 'n' : chomp = 1 ; break ;
+ case 'D' : def = localopt.arg ; break ;
+ case '!' : reapit = 1 ; break ;
+ default : dieusage() ;
+ }
+ }
+ argc -= localopt.ind ; argv += localopt.ind ;
+
+ if (!argc) dieusage() ;
+ if (!*argv[0] || strchr(argv[0], '=')) strerr_dief1x(100, "invalid variable name") ;
+ if (!stralloc_catb(&modif, "!", 2)
+ || !stralloc_cats(&modif, argv[0])
+ || !stralloc_catb(&modif, "=", 1))
+ strerr_diefu1sys(111, "stralloc_catb") ;
+ modifstart = modif.len ;
+ if (!slurp(&modif, 0)) strerr_diefu1sys(111, "slurp") ;
+ if (reapit)
+ {
+ char const *x = env_get2(envp, "!") ;
+ if (x)
+ {
+ uint64 pid ;
+ int wstat ;
+ if (!uint640_scan(x, &pid)) strerr_dieinvalid(100, "!") ;
+ if (waitpid(pid, &wstat, 0) < 0)
+ strerr_diefu1sys(111, "waitpid") ;
+ if (wait_estatus(wstat))
+ {
+ if (insist)
+ if (WIFSIGNALED(wstat)) strerr_dief1x(wait_estatus(wstat), "child process crashed") ;
+ else strerr_dief1x(wait_estatus(wstat), "child process exited non-zero") ;
+ else if (def)
+ {
+ modif.len = modifstart ;
+ if (!stralloc_cats(&modif, def)) strerr_diefu1sys(111, "stralloc_catb") ;
+ }
+ }
+ }
+ }
+ if (!stralloc_0(&modif)) strerr_diefu1sys(111, "stralloc_catb") ;
+ {
+ unsigned int reallen = str_len(modif.s + 2) ;
+ if (reallen < modif.len - 3)
+ {
+ if (insist)
+ strerr_dief1x(1, "stdin contained a null character") ;
+ else if (def)
+ {
+ modif.len = modifstart ;
+ if (!stralloc_catb(&modif, def, str_len(def)+1))
+ strerr_diefu1sys(111, "stralloc_catb") ;
+ strerr_warnw2x("stdin contained a null character", " - using default instead") ;
+ }
+ else
+ modif.len = reallen + 3 ;
+ }
+ if (chomp && (modif.s[modif.len - 2] == '\n'))
+ modif.s[--modif.len - 1] = 0 ;
+ }
+ if (!argv[1]) return 0 ;
+ pathexec_r(argv + 1, envp, env_len(envp), modif.s + !reapit * 2, modif.len - !reapit * 2) ;
+ strerr_dieexec(111, argv[1]) ;
+}