[comp.os.minix] xargs

iann@cmsfl@labtam.oz (Ian Nicholls) (03/02/90)

I enclose the source for the xargs command, which I find quite useful for
doing things to more files than the command line will allow.

Xargs makes creating libraries fast and easy, and (at work, where the access
times and compress work properly), for compressing files which I haven't
used in a while.

examples:
	xargs ar qv libc.a < liborder		# Create a new libc.a
	find . -name '*.s' -print | xargs rm	# Remove all .s files
	find . -type f ! -name '*.Z' \		# Compress old files.
	       -atime +60 -print  | xargs compress -v


/* xargs - Make and execute commands	     Author: Ian Nicholls:  1 Mar 90 */

/*
 * xargs  - Accept words from stdin until, combined with the arguments
 *	    given on the command line, just fit into the command line limit.
 *	    Then, execute the result.
 *
 * flags: -t		Print the command just before it is run
 *	  -l len	Use len as maximum line length (default and max 490)
 *	  -e ending	Append ending to the command before executing it.
 *
 * Returns: 0	no errors
 *	    1	If any system(3) call fails.
 *	    12	(ENOMEM) Line length too short to contain a single argument.
 *	    22	(EINVAL) Invalid argument given.
 *
 * Examples:	xargs ar qv libc.a < liborder		# Create a new libc.a
 *		find . -name '*.s' -print | xargs rm	# Remove all .s files
 *		find . -type f ! -name '*.Z' \		# Compress old files.
 *		       -atime +60 -print  | xargs compress -v
 *
 * Warnings:  If the command contains unquoted wildflags, then the system(3)
 *		call may expand this to larger than the maximum line size.
 *	      The command is not executed if nothing was read from stdin.
 *	  
 */
#define USAGE "usage: xargs [-t] [-l len] [-e endargs] command [args...]\n"

#include <stdio.h>
#include <errno.h>

#ifndef MAX_ARGLINE
# define MAX_ARGLINE 490
#endif
#ifndef min
# define min(a,b) ((a) < (b) ? (a) : (b))
#endif

extern void  perror();
extern void  exit();
extern char *strcat();
extern char *strcpy();

char outline[MAX_ARGLINE];
char inline[MAX_ARGLINE];
char startline[MAX_ARGLINE];
char *ending = NULL;
char traceflag = 0;

main(ac,av)
int ac;
char *av[];
{
  int outlen, inlen, startlen, endlen=0, i;
  extern char	*optarg;
  extern int optind;
  char errflg = 0;
  int maxline = MAX_ARGLINE;
  
  while ((i = getopt(ac, av, "tl:e:")) != EOF)
      switch (i) {
	  case 't': traceflag = 1;	  break;
	  case 'l': maxline = min(MAX_ARGLINE, atoi(optarg)); break;
	  case 'e': ending = optarg;	  break;
	  case '?': errflg++;		  break;
      }
  if (errflg)	{
      fprintf(stderr, USAGE);
      exit(EINVAL);
  }
  
  startline[0] = 0;
  if (optind == ac) {
      strcat(startline, "echo ");
  }
  else for ( ; optind < ac; optind++) {
      strcat(startline, av[optind]);
      strcat(startline, " ");
  }
  startlen = strlen(startline);
  if (ending) endlen = strlen(ending);
  maxline = maxline - 1 - endlen;	/* Pre-compute */
  
  strcpy(outline, startline);
  outlen = startlen;
  
  while (0 < gets(inline)) {
      inlen = strlen(inline);
      if (maxline <= (outlen + inlen)) {
  	  if (outlen == startlen) {
	      fprintf(stderr, "%s: Line length too short to process '%s'\n",
			av[0], inline);
	      exit(ENOMEM);
	  }
	  if (ending) strcat(outline, ending);
	  if (traceflag) fputs(outline,stderr);
	  if (-1 == system(outline)) {
	      perror("xargs");
	      exit(1);
	  }
	  strcpy(outline, startline);
	  outlen = startlen;
      }
      strcat(outline, inline);
      strcat(outline, " ");
      outlen = outlen + inlen + 1;
  }
  if (outlen != startlen) {
      if (ending) strcat(outline, ending);
      if (traceflag) fputs(outline,stderr);
      if (-1 == system(outline)) {
          perror("xargs");
          exit(1);
      }
  }
  return 0;
}
-- 
"He who laughs, lasts"
Ian Nicholls         Phone : +61 3 829 6088   Fax: +61 3 829 6860
Coles/Myer Ltd.      UUCP: labtam!cmsfl!iann  Email: iann%cmsfl@labtam.oz.au
L1 M11, PO Box 2000, Tooronga 3146, Australia