[hackers] [sbase] Add s-, t-, x-flags to and audit xargs(1) || FRIGN

From: <git_AT_suckless.org>
Date: Mon, 23 Mar 2015 18:35:49 +0100 (CET)

commit 4a75fd20f67ab01e977149603584fde2534a852c
Author: FRIGN <dev_AT_frign.de>
Date: Sun Mar 22 22:53:12 2015 +0100

    Add s-, t-, x-flags to and audit xargs(1)
    
    The flexible design already allowed to add these flags trivially.
    Drop the -I and -L-flags, which are XSI-extensions.
    The audit generally consisted of style-changes, dropping kitchen-
    sink functions, updating the usage and using estrtonum instead of
    strtol.

diff --git a/README b/README
index e5d9b5e..bbb6372 100644
--- a/README
+++ b/README
_AT_@ -87,7 +87,7 @@ The following tools are implemented ('*' == finished, '#' == UTF-8 support,
 =*| uudecode yes none
 =*| uuencode yes none
 #*| wc yes none
-= xargs no -I, -L, -p, -s, -t, -x
+=*| xargs no none (-p)
 =*| yes non-posix none
 
 The complement of sbase is ubase[1] which is Linux-specific and
diff --git a/xargs.1 b/xargs.1
index 04432fa..7283d1a 100644
--- a/xargs.1
+++ b/xargs.1
_AT_@ -1,15 +1,16 @@
-.Dd January 30, 2015
+.Dd March 22, 2015
 .Dt XARGS 1
 .Os sbase
 .Sh NAME
 .Nm xargs
-.Nd construct argument list(s) and execute command
+.Nd construct argument lists and execute command
 .Sh SYNOPSIS
 .Nm
-.Op Fl n Ar maxargs
-.Op Fl r
+.Op Fl rtx
 .Op Fl E Ar eofstr
-.Op Ar cmd Op Ar arg...
+.Op Fl n Ar num
+.Op Fl s Ar num
+.Op Ar cmd Op Ar arg ...
 .Sh DESCRIPTION
 .Nm
 reads space, tab, newline and EOF delimited strings from stdin
_AT_@ -31,9 +32,9 @@ newlines, up to the matching double quote. Any single character, including
 newlines, may be escaped by a backslash.
 .Sh OPTIONS
 .Bl -tag -width Ds
-.It Fl n Ar maxargs
+.It Fl n Ar num
 Use at most
-.Ar maxargs
+.Ar num
 arguments per command line.
 .It Fl r
 Do not run the command if there are no arguments. Normally the command is
_AT_@ -42,22 +43,54 @@ executed at least once even if there are no arguments.
 Use
 .Ar eofstr
 as a logical EOF marker.
+.It Fl s Ar num
+Use at most
+.Ar num
+bytes per command line.
+.It Fl t
+Write the command line to stderr before executing it.
+.It Fl x
+Terminate if the command line exceeds the system limit or the number of bytes
+given with the
+.Op Fl s
+flag.
 .El
 .Sh EXIT STATUS
-xargs exits with one of the following values:
+.Nm
+exits with one of the following values:
 .Bl -tag -width Ds
 .It 0
-All invocations of command returned a zero exit status.
+All invocations of
+.Ar cmd
+returned a zero exit status.
 .It 123
-One or more invocations of command returned a nonzero exit status.
+One or more invocations of
+.Ar cmd
+returned a nonzero exit status.
 .It 124
-The command exited with a 255 exit status.
+.Ar cmd
+exited with a 255 exit status.
 .It 125
-The command was killed or stopped by a signal.
+.Ar cmd
+was killed or stopped by a signal.
 .It 126
-The command was found but could not be executed.
+.Ar cmd
+was found but could not be executed.
 .It 127
-The command could not be found.
+.Ar cmd
+could not be found.
 .It 1
 Some other error occurred.
 .El
+.Sh STANDARDS
+The
+.Nm
+utility is compliant with the
+.St -p1003.1-2008
+specification except from prompting with the
+.Op Fl p
+flag.
+.Pp
+The
+.Op Fl r
+flag is an extension to that specification.
diff --git a/xargs.c b/xargs.c
index 8026b57..28dfaef 100644
--- a/xargs.c
+++ b/xargs.c
_AT_@ -2,6 +2,8 @@
 #include <sys/wait.h>
 
 #include <errno.h>
+#include <limits.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
_AT_@ -9,12 +11,9 @@
 
 #include "util.h"
 
-enum {
- NARGS = 10000
-};
+#define NARGS 10000
 
 static int inputc(void);
-static void deinputc(int);
 static void fillargbuf(int);
 static int eatspace(void);
 static int parsequote(int);
_AT_@ -23,14 +22,14 @@ static char *poparg(void);
 static void waitchld(void);
 static void spawn(void);
 
-static char *cmd[NARGS];
-static char *argb;
 static size_t argbsz;
 static size_t argbpos;
-static long maxargs = 0;
-static int nerrors = 0;
-static char *eofstr;
-static int rflag = 0, nflag = 0;
+static size_t maxargs = 0;
+static int nerrors = 0;
+static int rflag = 0, nflag = 0, tflag = 0, xflag = 0;
+static char *argb;
+static char *cmd[NARGS];
+static char *eofstr;
 
 static int
 inputc(void)
_AT_@ -39,14 +38,9 @@ inputc(void)
 
         ch = getc(stdin);
         if (ch == EOF && ferror(stdin))
- eprintf("stdin: read error:");
- return ch;
-}
+ eprintf("getc <stdin>:");
 
-static void
-deinputc(int ch)
-{
- ungetc(ch, stdin);
+ return ch;
 }
 
 static void
_AT_@ -69,7 +63,7 @@ eatspace(void)
                 case ' ': case '\t': case '\n':
                         break;
                 default:
- deinputc(ch);
+ ungetc(ch, stdin);
                         return ch;
                 }
         }
_AT_@ -89,6 +83,7 @@ parsequote(int q)
                         argbpos++;
                 }
         }
+
         return -1;
 }
 
_AT_@ -102,6 +97,7 @@ parseescape(void)
                 argbpos++;
                 return ch;
         }
+
         return -1;
 }
 
_AT_@ -137,9 +133,8 @@ poparg(void)
         }
 out:
         fillargbuf('\0');
- if (eofstr && strcmp(argb, eofstr) == 0)
- return NULL;
- return argb;
+
+ return (eofstr && !strcmp(argb, eofstr)) ? NULL : argb;
 }
 
 static void
_AT_@ -154,7 +149,7 @@ waitchld(void)
                 if (WEXITSTATUS(status) == 127 ||
                     WEXITSTATUS(status) == 126)
                         exit(WEXITSTATUS(status));
- if (status != 0)
+ if (status)
                         nerrors++;
         }
         if (WIFSIGNALED(status))
_AT_@ -165,6 +160,15 @@ static void
 spawn(void)
 {
         int savederrno;
+ char **p;
+
+ if (tflag) {
+ for (p = cmd; *p; p++) {
+ fputs(*p, stderr);
+ fputc(' ', stderr);
+ }
+ fputc('\n', stderr);
+ }
 
         switch (fork()) {
         case -1:
_AT_@ -181,26 +185,40 @@ spawn(void)
 static void
 usage(void)
 {
- eprintf("usage: %s [-n maxargs] [-r] [-E eofstr] [cmd [arg...]]\n", argv0);
+ eprintf("usage: %s [-rtx] [-E eofstr] [-n num] [-s num] [cmd [arg ...]]\n", argv0);
 }
 
 int
 main(int argc, char *argv[])
 {
         int leftover = 0;
- long argsz, argmaxsz;
+ size_t argsz, argmaxsz;
         char *arg = "";
         int i, a;
 
+ argmaxsz = sysconf(_SC_ARG_MAX);
+ if (argmaxsz < 0)
+ eprintf("sysconf:");
+ /* Leave some room for environment variables */
+ argmaxsz -= 4 * 1024;
+
         ARGBEGIN {
         case 'n':
                 nflag = 1;
- if ((maxargs = strtol(EARGF(usage()), NULL, 10)) <= 0)
- eprintf("%s: value for -n option should be >= 1\n", argv0);
+ maxargs = estrtonum(EARGF(usage()), 1, MIN(SIZE_MAX, LLONG_MAX));
                 break;
         case 'r':
                 rflag = 1;
                 break;
+ case 's':
+ argmaxsz = estrtonum(EARGF(usage()), 1, MIN(SIZE_MAX, LLONG_MAX));
+ break;
+ case 't':
+ tflag = 1;
+ break;
+ case 'x':
+ xflag = 1;
+ break;
         case 'E':
                 eofstr = EARGF(usage());
                 break;
_AT_@ -208,15 +226,9 @@ main(int argc, char *argv[])
                 usage();
         } ARGEND;
 
- argmaxsz = sysconf(_SC_ARG_MAX);
- if (argmaxsz < 0)
- eprintf("sysconf:");
- /* Leave some room for environment variables */
- argmaxsz -= 4 * 1024;
-
         do {
                 argsz = 0; i = 0; a = 0;
- if (argc > 0) {
+ if (argc) {
                         for (; i < argc; i++) {
                                 cmd[i] = estrdup(argv[i]);
                                 argsz += strlen(cmd[i]) + 1;
_AT_@ -226,11 +238,13 @@ main(int argc, char *argv[])
                         argsz += strlen(cmd[i]) + 1;
                         i++;
                 }
- while (leftover == 1 || (arg = poparg())) {
- if (argsz + strlen(arg) + 1 > argmaxsz ||
- i >= NARGS - 1) {
- if (strlen(arg) + 1 > argmaxsz)
- eprintf("insufficient argument space\n");
+ while (leftover || (arg = poparg())) {
+ if (argsz + strlen(arg) + 1 > argmaxsz || i >= NARGS - 1) {
+ if (strlen(arg) + 1 > argmaxsz) {
+ weprintf("insufficient argument space\n");
+ if (xflag)
+ exit(1);
+ }
                                 leftover = 1;
                                 break;
                         }
_AT_@ -239,13 +253,13 @@ main(int argc, char *argv[])
                         i++;
                         a++;
                         leftover = 0;
- if (nflag == 1 && a >= maxargs)
+ if (nflag && a >= maxargs)
                                 break;
                 }
                 cmd[i] = NULL;
- if (a >= maxargs && nflag == 1)
+ if (a >= maxargs && nflag)
                         spawn();
- else if (!a || (i == 1 && rflag == 1))
+ else if (!a || (i == 1 && rflag))
                         ;
                 else
                         spawn();
_AT_@ -255,5 +269,5 @@ main(int argc, char *argv[])
 
         free(argb);
 
- return nerrors > 0 ? 123 : 0;
+ return nerrors ? 123 : 0;
 }
Received on Mon Mar 23 2015 - 18:35:49 CET

This archive was generated by hypermail 2.3.0 : Mon Mar 23 2015 - 18:36:23 CET