/* one-time initialization. Should be called before any sf_ functions. */ void sf_init (void) { assert(_sf_stk == NULL); _sf_stk = (scanflags_t*) flex_alloc ( sizeof(scanflags_t) * (_sf_max = 32)); if (!_sf_stk) lerrsf_fatal(_("Unable to allocate %ld of stack"), (long)sizeof(scanflags_t)); _sf_stk[_sf_top_ix] = 0; }
/** Fork and exec entire filter chain. * @param chain The head of the chain. * @return true on success. */ bool filter_apply_chain(struct filter * chain) { int pid, pipes[2]; int r; const int readsz = 512; char *buf; /* * Tricky recursion, since we want to begin the chain at the END. * Why? Because we need all the forked processes to be children of * the main flex process. */ if (chain) filter_apply_chain(chain->next); else return true; /* * Now we are the right-most unprocessed link in the chain. */ fflush(stdout); fflush(stderr); if (pipe(pipes) == -1) flexerror(_("pipe failed")); if ((pid = fork()) == -1) flexerror(_("fork failed")); if (pid == 0) { /* child */ /* * We need stdin (the FILE* stdin) to connect to this new * pipe. There is no portable way to set stdin to a new file * descriptor, as stdin is not an lvalue on some systems * (BSD). So we dup the new pipe onto the stdin descriptor * and use a no-op fseek to sync the stream. This is a Hail * Mary situation. It seems to work. */ close(pipes[1]); clearerr(stdin); if (dup2(pipes[0], fileno(stdin)) == -1) flexfatal(_("dup2(pipes[0],0)")); close(pipes[0]); fseek(stdin, 0, SEEK_CUR); /* run as a filter, either internally or by exec */ if (chain->filter_func) { int r; if ((r = chain->filter_func(chain)) == -1) flexfatal(_("filter_func failed")); exit(0); } else { execvp(chain->argv[0], (char **const) (chain->argv)); lerrsf_fatal(_("exec of %s failed"), chain->argv[0]); } exit(1); } /* Parent */ close(pipes[0]); if (dup2(pipes[1], fileno(stdout)) == -1) flexfatal(_("dup2(pipes[1],1)")); close(pipes[1]); fseek(stdout, 0, SEEK_CUR); return true; }