summaryrefslogtreecommitdiff
path: root/src/execline/forstdin.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/execline/forstdin.c')
-rw-r--r--src/execline/forstdin.c89
1 files changed, 24 insertions, 65 deletions
diff --git a/src/execline/forstdin.c b/src/execline/forstdin.c
index b023640..d1e065c 100644
--- a/src/execline/forstdin.c
+++ b/src/execline/forstdin.c
@@ -2,6 +2,7 @@
#include <string.h>
#include <errno.h>
+#include <signal.h>
#include <skalibs/types.h>
#include <skalibs/sgetopt.h>
@@ -19,56 +20,31 @@
#define USAGE "forstdin [ -E | -e ] [ -p | -o okcode,okcode,... | -x breakcode,breakcode,... ] [ -N | -n ] [ -C | -c ] [ -0 | -d delim ] var command..."
#define dieusage() strerr_dieusage(100, USAGE)
-static genalloc *forstdin_pids_p = 0 ; /* minimize bss/data */
-
-static int fs_isok (unsigned short *tab, unsigned int n, int code)
-{
- 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, forstdin_pids_p) ;
- size_t len = genalloc_len(pid_t, forstdin_pids_p) ;
- int wstat ;
- for (;;)
- {
- ssize_t r = wait_pids_nohang(tab, len, &wstat) ;
- if (r <= 0) break ;
- tab[r-1] = tab[--len] ;
- }
- genalloc_setlen(pid_t, forstdin_pids_p, len) ;
- (void)sig ;
-}
-
int main (int argc, char const **argv)
{
- genalloc pids = GENALLOC_ZERO ;
+ el_forx_pidinfo_t pidinfo = EL_FORX_PIDINFO_ZERO ;
stralloc value = STRALLOC_ZERO ;
+ sigset_t emptyset ;
char const *delim = "\n" ;
size_t delimlen = 1 ;
size_t nbc = 0 ;
+ unsigned int maxpar = 1 ;
unsigned short okcodes[256] ;
int crunch = 0, chomp = 1, not = 1, eofcode = 1, doimport = 0 ;
PROG = "forstdin" ;
- forstdin_pids_p = &pids ;
+ el_forx_pidinfo = &pidinfo ;
+ sigemptyset(&emptyset) ;
{
subgetopt l = SUBGETOPT_ZERO ;
for (;;)
{
- int opt = subgetopt_r(argc, argv, "pNnCc0d:o:x:Ee", &l) ;
+ int opt = subgetopt_r(argc, argv, "pP:NnCc0d:o:x:Ee", &l) ;
if (opt == -1) break ;
switch (opt)
{
- case 'p' :
- {
- if (!genalloc_ready(pid_t, &pids, 1))
- strerr_diefu1sys(111, "genalloc_ready") ;
- break ;
- }
+ case 'p' : maxpar = 10000 ; break ;
+ case 'P' : if (!uint0_scan(l.arg, &maxpar)) dieusage() ; break ;
case 'N' : chomp = 0 ; break ;
case 'n' : chomp = 1 ; break ;
case 'C' : crunch = 1 ; break ;
@@ -92,15 +68,16 @@ int main (int argc, char const **argv)
}
if (argc < 2) dieusage() ;
if (!argv[0][0] || strchr(argv[0], '=')) strerr_dief1x(100, "invalid variable name") ;
+ if (maxpar < 1) maxpar = 1 ;
+ if (maxpar >= 10000) maxpar = 10000 ;
+ if (!sig_catch(SIGCHLD, &el_forx_sigchld_handler))
+ strerr_diefu1sys(111, "install SIGCHLD handler") ;
- if (pids.s)
- {
- if (!sig_catch(SIGCHLD, &parallel_sigchld_handler))
- strerr_diefu1sys(111, "install SIGCHLD handler") ;
- }
+ pid_t pidtab[maxpar] ;
+ pidinfo.tab = pidtab ;
+ sig_block(SIGCHLD) ;
for (;;)
{
- pid_t pid ;
value.len = 0 ;
if (delimlen)
{
@@ -125,34 +102,16 @@ int main (int argc, char const **argv)
}
eofcode = 0 ;
if (!stralloc_0(&value)) strerr_diefu1sys(111, "stralloc_0") ;
- if (pids.s) sig_block(SIGCHLD) ;
- pid = el_modif_and_spawn(argv + 1, argv[0], value.s, doimport) ;
- if (!pid) strerr_diefu2sys(111, "spawn ", argv[1]) ;
- if (pids.s)
- {
- if (!genalloc_append(pid_t, &pids, &pid))
- strerr_diefu1sys(111, "genalloc_append") ;
- sig_unblock(SIGCHLD) ;
- }
- else
- {
- int wstat ;
- if (wait_pid(pid, &wstat) < 0)
- strerr_diefu2sys(111, "wait for ", argv[1]) ;
- if (not == fs_isok(okcodes, nbc, wait_estatus(wstat)))
- return wait_estatus(wstat) ;
- }
- }
- if (pids.s)
- {
- sigset_t empty ;
- sigemptyset(&empty) ;
- sig_block(SIGCHLD) ;
- for (;;)
+ pidtab[pidinfo.len] = el_modif_and_spawn(argv + 1, argv[0], value.s, doimport) ;
+ if (!pidtab[pidinfo.len]) strerr_diefu2sys(111, "spawn ", argv[1]) ;
+ pidinfo.len++ ;
+ while (pidinfo.len >= maxpar)
{
- if (!pids.len) break ;
- sigsuspend(&empty) ;
+ sigsuspend(&emptyset) ;
+ if (maxpar == 1 && not == el_forx_isok(okcodes, nbc, wait_estatus(pidinfo.wstat)))
+ return wait_estatus(pidinfo.wstat) ;
}
}
+ while (pidinfo.len) sigsuspend(&emptyset) ;
return eofcode ;
}