summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2015-02-26 01:48:50 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2015-02-26 01:48:50 +0000
commit4d067b3020104a8b19a34fa4d3b6e5e8f3eb036a (patch)
tree5c5752681d5fef7837d22a5d8fb590d4b6003d1d /src
parente1fe79a9e705e3cab8f632cdbe8e1774cdef2761 (diff)
downloadexecline-4d067b3020104a8b19a34fa4d3b6e5e8f3eb036a.tar.gz
execline-4d067b3020104a8b19a34fa4d3b6e5e8f3eb036a.tar.xz
execline-4d067b3020104a8b19a34fa4d3b6e5e8f3eb036a.zip
- added forstdin v2.1.1.0
 - rewrote forbacktickx as a wrapper around forstdin
 - removed el_obsolescent
 - version: rc for 2.1.1.0
Diffstat (limited to 'src')
-rw-r--r--src/execline/deps-exe/forbacktickx1
-rw-r--r--src/execline/deps-exe/forstdin2
-rw-r--r--src/execline/forbacktickx.c155
-rw-r--r--src/execline/forstdin.c157
-rw-r--r--src/include/execline/execline.h1
-rw-r--r--src/libexecline/deps-lib/execline1
-rw-r--r--src/libexecline/el_obsolescent.c10
7 files changed, 211 insertions, 116 deletions
diff --git a/src/execline/deps-exe/forbacktickx b/src/execline/deps-exe/forbacktickx
index 97021b5..e7187fe 100644
--- a/src/execline/deps-exe/forbacktickx
+++ b/src/execline/deps-exe/forbacktickx
@@ -1,2 +1 @@
-${LIBEXECLINE}
 -lskarnet
diff --git a/src/execline/deps-exe/forstdin b/src/execline/deps-exe/forstdin
new file mode 100644
index 0000000..97021b5
--- /dev/null
+++ b/src/execline/deps-exe/forstdin
@@ -0,0 +1,2 @@
+${LIBEXECLINE}
+-lskarnet
diff --git a/src/execline/forbacktickx.c b/src/execline/forbacktickx.c
index 51f308e..0e58106 100644
--- a/src/execline/forbacktickx.c
+++ b/src/execline/forbacktickx.c
@@ -1,43 +1,23 @@
 /* ISC license. */
 
-#include <sys/types.h>
-#include <errno.h>
-#include <skalibs/sgetopt.h>
+#include <skalibs/ushort.h>
 #include <skalibs/bytestr.h>
-#include <skalibs/buffer.h>
-#include <skalibs/fmtscan.h>
+#include <skalibs/sgetopt.h>
 #include <skalibs/strerr2.h>
-#include <skalibs/stralloc.h>
-#include <skalibs/genalloc.h>
-#include <skalibs/env.h>
 #include <skalibs/djbunix.h>
-#include <skalibs/skamisc.h>
-#include <skalibs/netstring.h>
-#include <skalibs/ushort.h>
 #include <execline/config.h>
 #include <execline/execline.h>
 
 #define USAGE "forbacktickx [ -p | -o okcode,okcode,... | -x breakcode,breakcode,... ] [ -n ] [ -C | -c ] [ -0 | -d delim ] var { backtickcmd... } command..."
 #define dieusage() strerr_dieusage(100, USAGE)
 
-static int isok (unsigned short *tab, unsigned int n, int code)
-{
-  register unsigned int i = 0 ;
-  for (; i < n ; i++) if ((unsigned short)code == tab[i]) break ;
-  return i < n ;
-}
+#define DELIM_DEFAULT " \n\r\t"
 
 int main (int argc, char const **argv, char const *const *envp)
 {
-  genalloc pids = GENALLOC_ZERO ; /* pid_t */
-  char const *delim = " \n\r\t" ;
-  unsigned int delimlen = 4 ;
-  char const *x ;
-  pid_t pidw ;
-  int fd, argc1 ;
-  unsigned short okcodes[256] ;
-  unsigned int nbc = 0 ;
-  int crunch = 0, chomp = 0, not = 1 ;
+  char const *delim = DELIM_DEFAULT ;
+  char const *codes = 0 ;
+  int crunch = 0, chomp = 0, not = 1, par = 0 ;
   PROG = "forbacktickx" ;
   {
     subgetopt_t l = SUBGETOPT_ZERO ;
@@ -48,100 +28,69 @@ int main (int argc, char const **argv, char const *const *envp)
       switch (opt)
       {
 	case 'e' : break ; /* compat */
-        case 'p' :
-        {
-          if (!genalloc_ready(pid_t, &pids, 2))
-            strerr_diefu1sys(111, "genalloc_ready") ;
-          break ;
-        }
+        case 'p' : par = 1 ; break ;
         case 'n' : chomp = 1 ; break ;
         case 'C' : crunch = 1 ; break ;
         case 'c' : crunch = 0 ; break ;
-        case '0' : delim = "" ; delimlen = 1 ; break ;
-        case 'd' : delim = l.arg ; delimlen = str_len(delim) ; break ;
+        case '0' : delim = 0 ; break ;
+        case 'd' : delim = l.arg ; break ;
         case 'o' :
-          not = 0 ;
+        {
+          unsigned short okcodes[256] ;
+          unsigned int nbc ;
           if (!ushort_scanlist(okcodes, 256, l.arg, &nbc)) dieusage() ;
+          codes = l.arg ;
+          not = 0 ;
           break ;
+        }
         case 'x' :
-          not = 1 ;
+        {
+          unsigned short okcodes[256] ;
+          unsigned int nbc ;
           if (!ushort_scanlist(okcodes, 256, l.arg, &nbc)) dieusage() ;
+          codes = l.arg ;
+          not = 1 ;
           break ;
+        }
         default : dieusage() ;
       }
     }
     argc -= l.ind ; argv += l.ind ;
   }
   if (argc < 2) dieusage() ;
-  x = argv[0] ; if (!*x) dieusage() ;
-  argv++ ; argc-- ;
-  argc1 = el_semicolon(argv) ;
-  if (!argc1) strerr_dief1x(100, "empty block") ;
-  if (argc1 >= argc) strerr_dief1x(100, "unterminated block") ;
-  argv[argc1] = 0 ;
-  pidw = el_spawn1(argv[0], argv, envp, &fd, 1) ;
-  if (!pidw) strerr_diefu2sys(111, "spawn ", argv[0]) ;
+  if (!argv[0][0]) dieusage() ;
+  if (!argv[1][0]) strerr_dief1x(100, "empty block") ;
   {
-    char buf[BUFFER_INSIZE] ;
-    buffer b = BUFFER_INIT(&buffer_read, fd, buf, BUFFER_INSIZE) ;
-    stralloc modif = STRALLOC_ZERO ;
-    unsigned int envlen = env_len(envp) ;
-    unsigned int modifstart = str_len(x)+1 ;
-    char const *newenv[envlen + 2] ;
-    if (!stralloc_ready(&modif, modifstart+1))
-      strerr_diefu1sys(111, "stralloc_ready") ;
-    byte_copy(modif.s, modifstart-1, x) ;
-    modif.s[modifstart-1] = '=' ;
-    for (;;)
+    unsigned int m = 0, i = 1 ;
+    char const *newargv[argc + 15] ;
+    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 "unexport" ;
+    newargv[m++] = "!" ;
+    newargv[m++] = EXECLINE_BINPREFIX "forstdin" ;
+    if (par) newargv[m++] = "-p" ;
+    if (chomp) newargv[m++] = "-n" ;
+    if (crunch) newargv[m++] = "-C" ;
+    if (!delim) newargv[m++] = "-0" ;
+    else if (str_diff(delim, DELIM_DEFAULT))
     {
-      pid_t pid ;
-      modif.len = modifstart ;
-      if (delimlen)
-      {
-        register int r = skagetlnsep(&b, &modif, delim, delimlen) ;
-        if (!r) break ;
-        else if (r < 0)
-        {
-          if (errno != EPIPE) strerr_diefu1sys(111, "skagetlnsep") ;
-          if (chomp) break ;
-        }
-        else modif.len-- ;
-        if ((modif.len == modifstart) && crunch) continue ;
-      }
-      else
-      {
-        unsigned int unread = 0 ;
-        if (netstring_get(&b, &modif, &unread) <= 0)
-        {
-          if (netstring_okeof(&b, unread)) break ;
-          else strerr_diefu1sys(111, "netstring_get") ;
-        }
-      }
-      if (!stralloc_0(&modif)) strerr_diefu1sys(111, "stralloc_0") ;
-      if (!env_merge(newenv, envlen+2, envp, envlen, modif.s, modif.len))
-        strerr_diefu1sys(111, "merge environment") ;
-      pid = el_spawn0(argv[argc1 + 1], argv + argc1 + 1, newenv) ;
-      if (!pid) strerr_diefu2sys(111, "spawn ", argv[argc1+1]) ;
-      if (pids.s)
-      {
-        if (!genalloc_append(pid_t, &pids, &pid))
-          strerr_diefu1sys(111, "genalloc_append") ;
-      }
-      else
-      {
-        int wstat ;
-        if (wait_pid(pid, &wstat) < 0)
-          strerr_diefu2sys(111, "wait for ", argv[argc1 + 1]) ;
-        if (not == isok(okcodes, nbc, wait_estatus(wstat)))
-          return wait_estatus(wstat) ;
-      }
+      newargv[m++] = "-d" ;
+      newargv[m++] = delim ;
+    }
+    if (codes)
+    {
+      newargv[m++] = not ? "-x" : "-o" ;
+      newargv[m++] = codes ;
     }
-    stralloc_free(&modif) ;
+    newargv[m++] = "--" ;
+    newargv[m++] = argv[0] ;
+    while (argv[i]) newargv[m++] = argv[i++] ;
+    newargv[m++] = 0 ;
+    pathexec_run(newargv[0], newargv, envp) ;
+    strerr_dieexec(111, newargv[0]) ;
   }
-  fd_close(fd) ;
-  if (!genalloc_append(pid_t, &pids, &pidw))
-    strerr_diefu1sys(111, "genalloc_append") ;
-  if (!waitn(genalloc_s(pid_t, &pids), genalloc_len(pid_t, &pids)))
-    strerr_diefu1sys(111, "waitn") ;
-  return 0 ;
 }
diff --git a/src/execline/forstdin.c b/src/execline/forstdin.c
new file mode 100644
index 0000000..1e9d5e6
--- /dev/null
+++ b/src/execline/forstdin.c
@@ -0,0 +1,157 @@
+/* ISC license. */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <skalibs/sgetopt.h>
+#include <skalibs/bytestr.h>
+#include <skalibs/buffer.h>
+#include <skalibs/fmtscan.h>
+#include <skalibs/strerr2.h>
+#include <skalibs/stralloc.h>
+#include <skalibs/genalloc.h>
+#include <skalibs/env.h>
+#include <skalibs/sig.h>
+#include <skalibs/djbunix.h>
+#include <skalibs/skamisc.h>
+#include <skalibs/netstring.h>
+#include <skalibs/ushort.h>
+#include <execline/config.h>
+#include <execline/execline.h>
+
+#define USAGE "forstdin [ -p | -o okcode,okcode,... | -x breakcode,breakcode,... ] [ -n ] [ -C | -c ] [ -0 | -d delim ] var command..."
+#define dieusage() strerr_dieusage(100, USAGE)
+
+static genalloc pids = GENALLOC_ZERO ; /* pid_t */
+
+static int isok (unsigned short *tab, unsigned int n, int code)
+{
+  register unsigned int i = 0 ;
+  for (; i < n ; i++) if ((unsigned short)code == tab[i]) break ;
+  return i < n ;
+}
+
+static void parallel_sigchld_handler (int sig)
+{
+  pid_t *tab = genalloc_s(pid_t, &pids) ;
+  unsigned int len = genalloc_len(pid_t, &pids) ;
+  int wstat ;
+  for (;;)
+  {
+    register int r = wait_pids_nohang(tab, len, &wstat) ;
+    if (r <= 0) break ;
+    tab[r-1] = tab[--len] ;
+  }
+  genalloc_setlen(pid_t, &pids, len) ;
+  (void)sig ;
+}
+
+int main (int argc, char const **argv, char const *const *envp)
+{
+  char const *delim = " \n\r\t" ;
+  unsigned int delimlen = 4 ;
+  unsigned short okcodes[256] ;
+  unsigned int nbc = 0 ;
+  int crunch = 0, chomp = 0, not = 1 ;
+  PROG = "forstdin" ;
+  {
+    subgetopt_t l = SUBGETOPT_ZERO ;
+    for (;;)
+    {
+      register int opt = subgetopt_r(argc, argv, "pnCc0d:o:x:", &l) ;
+      if (opt == -1) break ;
+      switch (opt)
+      {
+        case 'p' :
+        {
+          if (!genalloc_ready(pid_t, &pids, 1))
+            strerr_diefu1sys(111, "genalloc_ready") ;
+          break ;
+        }
+        case 'n' : chomp = 1 ; break ;
+        case 'C' : crunch = 1 ; break ;
+        case 'c' : crunch = 0 ; break ;
+        case '0' : delim = "" ; delimlen = 1 ; break ;
+        case 'd' : delim = l.arg ; delimlen = str_len(delim) ; break ;
+        case 'o' :
+          not = 0 ;
+          if (!ushort_scanlist(okcodes, 256, l.arg, &nbc)) dieusage() ;
+          break ;
+        case 'x' :
+          not = 1 ;
+          if (!ushort_scanlist(okcodes, 256, l.arg, &nbc)) dieusage() ;
+          break ;
+        default : dieusage() ;
+      }
+    }
+    argc -= l.ind ; argv += l.ind ;
+  }
+  if (argc < 2) dieusage() ;
+  {
+    stralloc modif = STRALLOC_ZERO ;
+    unsigned int envlen = env_len(envp) ;
+    unsigned int modifstart = str_len(argv[0])+1 ;
+    char const *newenv[envlen + 2] ;
+    if (!stralloc_ready(&modif, modifstart+1))
+      strerr_diefu1sys(111, "stralloc_ready") ;
+    byte_copy(modif.s, modifstart-1, argv[0]) ;
+    modif.s[modifstart-1] = '=' ;
+    if (pids.s)
+    {
+      if (sig_catch(SIGCHLD, &parallel_sigchld_handler) < 0)
+        strerr_diefu2sys(111, "install", " SIGCHLD handler") ;
+    }
+    for (;;)
+    {
+      pid_t pid ;
+      modif.len = modifstart ;
+      if (delimlen)
+      {
+        register int r = skagetlnsep(buffer_0, &modif, delim, delimlen) ;
+        if (!r) break ;
+        else if (r < 0)
+        {
+          if (errno != EPIPE) strerr_diefu1sys(111, "skagetlnsep") ;
+          if (chomp) break ;
+        }
+        else modif.len-- ;
+        if ((modif.len == modifstart) && crunch) continue ;
+      }
+      else
+      {
+        unsigned int unread = 0 ;
+        if (netstring_get(buffer_0, &modif, &unread) <= 0)
+        {
+          if (netstring_okeof(buffer_0, unread)) break ;
+          else strerr_diefu1sys(111, "netstring_get") ;
+        }
+      }
+      if (!stralloc_0(&modif)) strerr_diefu1sys(111, "stralloc_0") ;
+      if (!env_merge(newenv, envlen+2, envp, envlen, modif.s, modif.len))
+        strerr_diefu1sys(111, "merge environment") ;
+      pid = el_spawn0(argv[1], argv + 1, newenv) ;
+      if (!pid) strerr_diefu2sys(111, "spawn ", argv[1]) ;
+      if (pids.s)
+      {
+        if (!genalloc_append(pid_t, &pids, &pid))
+          strerr_diefu1sys(111, "genalloc_append") ;
+      }
+      else
+      {
+        int wstat ;
+        if (wait_pid(pid, &wstat) < 0)
+          strerr_diefu2sys(111, "wait for ", argv[1]) ;
+        if (not == isok(okcodes, nbc, wait_estatus(wstat)))
+          return wait_estatus(wstat) ;
+      }
+    }
+    stralloc_free(&modif) ;
+  }
+  if (pids.s)
+  {
+    if (sig_restore(SIGCHLD) < 0)
+      strerr_diefu2sys(111, "restore", " SIGCHLD handler") ;
+    if (!waitn(genalloc_s(pid_t, &pids), genalloc_len(pid_t, &pids)))
+      strerr_diefu1sys(111, "waitn") ;
+  }
+  return 0 ;
+}
diff --git a/src/include/execline/execline.h b/src/include/execline/execline.h
index a5c16ad..1f1ec68 100644
--- a/src/include/execline/execline.h
+++ b/src/include/execline/execline.h
@@ -15,7 +15,6 @@
 
 extern int el_vardupl (char const *, char const *, unsigned int) gccattr_pure ;
 extern unsigned int el_getstrict (void) gccattr_const ;
-extern void el_obsolescent (void) ;
 
 
 /* Environment shifting */
diff --git a/src/libexecline/deps-lib/execline b/src/libexecline/deps-lib/execline
index 69d483d..f3e4e49 100644
--- a/src/libexecline/deps-lib/execline
+++ b/src/libexecline/deps-lib/execline
@@ -1,6 +1,5 @@
 el_execsequence.o
 el_getstrict.o
-el_obsolescent.o
 el_popenv.o
 el_pushenv.o
 el_semicolon.o
diff --git a/src/libexecline/el_obsolescent.c b/src/libexecline/el_obsolescent.c
deleted file mode 100644
index 42b8a11..0000000
--- a/src/libexecline/el_obsolescent.c
+++ /dev/null
@@ -1,10 +0,0 @@
-/* ISC license. */
-
-#include <skalibs/strerr2.h>
-#include <execline/execline.h>
-
-void el_obsolescent (void)
-{
-  if (el_getstrict())
-    strerr_warnw3x("this command is marked as obsolescent. Please update your script to use the ", PROG, "x command instead.") ;
-}