/* xargs.c - Run command with arguments taken from stdin.
 *
 * Copyright 2011 Rob Landley <rob@landley.net>
 *
 * See http://opengroup.org/onlinepubs/9699919799/utilities/xargs.html
 *
 * TODO: Rich's whitespace objection, env size isn't fixed anymore.

USE_XARGS(NEWTOY(xargs, "^I:E:L#ptxrn#<1s#0", TOYFLAG_USR|TOYFLAG_BIN))

config XARGS
  bool "xargs"
  default y
  help
    usage: xargs [-ptxr0] [-s NUM] [-n NUM] [-L NUM] [-E STR] COMMAND...

    Run command line one or more times, appending arguments from stdin.

    If command exits with 255, don't launch another even if arguments remain.

    -s	Size in bytes per command line
    -n	Max number of arguments per command
    -0	Each argument is NULL terminated, no whitespace or quote processing
    #-p	Prompt for y/n from tty before running each command
    #-t	Trace, print command line to stderr
    #-x	Exit if can't fit everything in one command
    #-r	Don't run command with empty input
    #-L	Max number of lines of input per command
    -E	stop at line matching string

config XARGS_PEDANTIC
  bool "TODO xargs pedantic posix compatability"
  default n
  depends on XARGS
  help
    This version supports insane posix whitespace handling rendered obsolete
    by -0 mode.
*/

#define FOR_xargs
#include "toys.h"

GLOBALS(
  long max_bytes;
  long max_entries;
  long L;
  char *eofstr;
  char *I;

  long entries, bytes;
  char delim;
)

// If out==NULL count TT.bytes and TT.entries, stopping at max.
// Otherwise, fill out out[]

// Returning NULL means need more data.
// Returning char * means hit data limits, start of data left over
// Returning 1 means hit data limits, but consumed all data
// Returning 2 means hit -E eofstr

static char *handle_entries(char *data, char **entry)
{
  if (TT.delim) {
    char *s = data;

    // Chop up whitespace delimited string into args
    while (*s) {
      char *save;

      while (isspace(*s)) {
        if (entry) *s = 0;
        s++;
      }

      if (TT.max_entries && TT.entries >= TT.max_entries)
        return *s ? s : (char *)1;

      if (!*s) break;
      save = s;

      for (;;) {
        if (++TT.bytes >= TT.max_bytes && TT.max_bytes) return save;
        if (!*s || isspace(*s)) break;
        s++;
      }
      if (TT.eofstr) {
        int len = s-save;
        if (len == strlen(TT.eofstr) && !strncmp(save, TT.eofstr, len))
          return (char *)2;
      }
      if (entry) entry[TT.entries] = save;
      ++TT.entries;
    }

  // -0 support
  } else {
    TT.bytes += strlen(data)+1;
    if (TT.max_bytes && TT.bytes >= TT.max_bytes) return data;
    if (TT.max_entries && TT.entries >= TT.max_entries)
      return (char *)1;
    if (entry) entry[TT.entries] = data;
    TT.entries++;
  }

  return NULL;
}

void xargs_main(void)
{
  struct double_list *dlist = NULL, *dtemp;
  int entries, bytes, done = 0, status;
  char *data = NULL, **out;

  if (!(toys.optflags & FLAG_0)) TT.delim = '\n';

  // If no optargs, call echo.
  if (!toys.optc) {
    free(toys.optargs);
    *(toys.optargs = xzalloc(2*sizeof(char *)))="echo";
    toys.optc = 1;
  }

  for (entries = 0, bytes = -1; entries < toys.optc; entries++, bytes++)
    bytes += strlen(toys.optargs[entries]);

  // Loop through exec chunks.
  while (data || !done) {
    TT.entries = 0;
    TT.bytes = bytes;

    // Loop reading input
    for (;;) {

      // Read line
      if (!data) {
        ssize_t l = 0;
        l = getdelim(&data, (size_t *)&l, TT.delim, stdin);

        if (l<0) {
          data = 0;
          done++;
          break;
        }
      }
      dlist_add(&dlist, data);

      // Count data used
      data = handle_entries(data, NULL);
      if (!data) continue;
      if (data == (char *)2) done++;
      if ((long)data <= 2) data = 0;
      else data = xstrdup(data);

      break;
    }

    // Accumulate cally thing

    if (data && !TT.entries) error_exit("argument too long");
    out = xzalloc((entries+TT.entries+1)*sizeof(char *));

    // Fill out command line to exec
    memcpy(out, toys.optargs, entries*sizeof(char *));
    TT.entries = 0;
    TT.bytes = bytes;
    if (dlist) dlist->prev->next = 0;
    for (dtemp = dlist; dtemp; dtemp = dtemp->next)
      handle_entries(dtemp->data, out+entries);

    pid_t pid=xfork();
    if (!pid) {
      xclose(0);
      open("/dev/null", O_RDONLY);
      xexec(out);
    }
    waitpid(pid, &status, 0);
    status = WIFEXITED(status) ? WEXITSTATUS(status) : WTERMSIG(status)+127;

    // Abritrary number of execs, can't just leak memory each time...
    while (dlist) {
      struct double_list *dtemp = dlist->next;

      free(dlist->data);
      free(dlist);
      dlist = dtemp;
    }
    free(out);
  }
}
