summaryrefslogtreecommitdiff
path: root/usr/src/cmd/xargs/xargs.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/xargs/xargs.c')
-rw-r--r--usr/src/cmd/xargs/xargs.c811
1 files changed, 261 insertions, 550 deletions
diff --git a/usr/src/cmd/xargs/xargs.c b/usr/src/cmd/xargs/xargs.c
index 87f7a04e13..33ba01f3ea 100644
--- a/usr/src/cmd/xargs/xargs.c
+++ b/usr/src/cmd/xargs/xargs.c
@@ -19,6 +19,16 @@
* CDDL HEADER END
*/
/*
+ * Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
+ *
+ * Portions of this file developed by DEY Storage Systems, Inc. are licensed
+ * under the terms of the Common Development and Distribution License (CDDL)
+ * version 1.0 only. The use of subsequent versions of the License are
+ * is specifically prohibited unless those terms are not in conflict with
+ * version 1.0 of the License. You can find this license on-line at
+ * http://www.illumos.org/license/CDDL
+ */
+/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -27,8 +37,6 @@
/* All Rights Reserved */
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
@@ -62,11 +70,32 @@
#define QBUF_STARTLEN 255 /* start size of growable string buffer */
#define QBUF_INC 100 /* how much to grow a growable string by */
+/* We use these macros to help make formatting look "consistent" */
+#define EMSG(s) ermsg(gettext(s "\n"))
+#define EMSG2(s, a) ermsg(gettext(s "\n"), a)
+#define PERR(s) perror(gettext("xargs: " s))
+
+/* Some common error messages */
+
+#define LIST2LONG "Argument list too long"
+#define ARG2LONG "A single argument was greater than %d bytes"
+#define MALLOCFAIL "Memory allocation failure"
+#define CORRUPTFILE "Corrupt input file"
+#define WAITFAIL "Wait failure"
+#define CHILDSIG "Child killed with signal %d"
+#define CHILDFAIL "Command could not continue processing data"
+#define FORKFAIL "Could not fork child"
+#define EXECFAIL "Could not exec command"
+#define MISSQUOTE "Missing quote"
+#define BADESCAPE "Incomplete escape"
+#define IBUFOVERFLOW "Insert buffer overflow"
+
+#define _(x) gettext(x)
+
static wctype_t blank;
static char *arglist[MAXARGS+1];
-static char argbuf[BUFSIZE+1];
-static char *next = argbuf;
-static char *lastarg = "";
+static char argbuf[BUFSIZE * 2 + 1];
+static char lastarg[BUFSIZE + 1];
static char **ARGV = arglist;
static char *LEOF = "_";
static char *INSPAT = INSPAT_STR;
@@ -78,7 +107,6 @@ static struct inserts {
char *p_skel; /* ptr to arg template */
} saveargv[MAXINSERTS];
-static off_t file_offset = 0;
static int PROMPT = -1;
static int BUFLIM = BUFSIZE;
static int N_ARGS = 0;
@@ -92,28 +120,13 @@ static int OK = TRUE;
static int LEGAL = FALSE;
static int TRACE = FALSE;
static int INSERT = FALSE;
+static int ZERO = FALSE;
static int linesize = 0;
static int ibufsize = 0;
static int exitstat = 0; /* our exit status */
static int mac; /* modified argc, after parsing */
static char **mav; /* modified argv, after parsing */
static int n_inserts; /* # of insertions. */
-static int inquote = 0; /* processing a quoted string */
-static int save_index = 0;
-
-/*
- * the pio structure is used to save any pending input before the
- * user replies to a prompt. the pending input is saved here,
- * for the appropriate processing later.
- */
-typedef struct pio {
- struct pio *next; /* next in stack */
- char *start; /* starting addr of the buffer */
- char *cur; /* ptr to current char in buf */
- size_t length; /* number of bytes remaining */
-} pio;
-
-static pio *queued_data = NULL;
/* our usage message: */
#define USAGEMSG "Usage: xargs: [-t] [-p] [-e[eofstr]] [-E eofstr] "\
@@ -121,21 +134,16 @@ static pio *queued_data = NULL;
"[cmd [args ...]]\n"
static int echoargs();
-static int getchr(void);
-static wchar_t getwchr(void);
-static void ungetwchr(wchar_t);
+static wint_t getwchr(char *, size_t *);
static int lcall(char *sub, char **subargs);
-static int xindex(char *as1, char *as2);
static void addibuf(struct inserts *p);
static void ermsg(char *messages, ...);
static char *addarg(char *arg);
-static char *checklen(char *arg);
-static size_t store_wchr(char **, size_t *, size_t, wchar_t);
-static char *getarg();
+static void store_str(char **, char *, size_t);
+static char *getarg(char *);
static char *insert(char *pattern, char *subst);
static void usage();
static void parseargs();
-static void saveinput();
int
main(int argc, char **argv)
@@ -144,8 +152,9 @@ main(int argc, char **argv)
struct inserts *psave;
int c;
int initsize;
- char *cmdname, *initbuf, **initlist;
-
+ char *cmdname, **initlist;
+ char *arg;
+ char *next;
/* initialization */
blank = wctype("blank");
@@ -157,22 +166,26 @@ main(int argc, char **argv)
#endif
(void) textdomain(TEXT_DOMAIN);
if (init_yes() < 0) {
- ermsg(gettext(ERR_MSG_INIT_YES), strerror(errno));
+ ermsg(_(ERR_MSG_INIT_YES), strerror(errno));
exit(1);
}
parseargs(argc, argv);
/* handling all of xargs arguments: */
- while ((c = getopt(mac, mav, "tpe:E:I:i:L:l:n:s:x")) != EOF) {
+ while ((c = getopt(mac, mav, "0tpe:E:I:i:L:l:n:s:x")) != EOF) {
switch (c) {
+ case '0':
+ ZERO = TRUE;
+ break;
+
case 't': /* -t: turn trace mode on */
TRACE = TRUE;
break;
case 'p': /* -p: turn on prompt mode. */
if ((PROMPT = open("/dev/tty", O_RDONLY)) == -1) {
- perror(gettext("can't read from tty for -p"));
+ PERR("can't read from tty for -p");
} else {
TRACE = TRUE;
}
@@ -202,8 +215,8 @@ main(int argc, char **argv)
N_ARGS = 0;
INSPAT = optarg;
if (*optarg == '\0') {
- ermsg(gettext(
- "Option requires an argument: -%c\n"), c);
+ ermsg(_("Option requires an argument: -%c\n"),
+ c);
}
break;
@@ -245,8 +258,8 @@ main(int argc, char **argv)
N_ARGS = 0;
INSERT = FALSE;
if ((PER_LINE = atoi(optarg)) <= 0) {
- ermsg(gettext("#lines must be positive "
- "int: %s\n"), optarg);
+ ermsg(_("#lines must be positive int: %s\n"),
+ optarg);
}
break;
@@ -275,8 +288,8 @@ main(int argc, char **argv)
* number *is* required here:
*/
if ((N_ARGS = atoi(optarg)) <= 0) {
- ermsg(gettext("#args must be positive "
- "int: %s\n"), optarg);
+ ermsg(_("#args must be positive int: %s\n"),
+ optarg);
} else {
LEGAL = DASHX || N_ARGS == 1;
INSERT = PER_LINE = FALSE;
@@ -286,9 +299,8 @@ main(int argc, char **argv)
case 's': /* -s size: set max size of each arg list */
BUFLIM = atoi(optarg);
if (BUFLIM > BUFSIZE || BUFLIM <= 0) {
- ermsg(gettext(
- "0 < max-cmd-line-size <= %d: "
- "%s\n"), BUFSIZE, optarg);
+ ermsg(_("0 < max-cmd-line-size <= %d: %s\n"),
+ BUFSIZE, optarg);
}
break;
@@ -300,9 +312,7 @@ main(int argc, char **argv)
/*
* bad argument. complain and get ready to die.
*/
- ERR = TRUE;
usage();
-
exit(2);
break;
}
@@ -313,7 +323,6 @@ main(int argc, char **argv)
* we exit early.
*/
if (OK == FALSE) {
- ERR = TRUE;
usage();
exit(2);
}
@@ -346,9 +355,9 @@ main(int argc, char **argv)
* work to do:
*/
if (INSERT && ! ERR) {
- if (xindex(*mav, INSPAT) != -1) {
+ if (strstr(*mav, INSPAT) != NULL) {
if (++n_inserts > MAXINSERTS) {
- ermsg(gettext("too many args "
+ ermsg(_("too many args "
"with %s\n"), INSPAT);
ERR = TRUE;
}
@@ -362,39 +371,77 @@ main(int argc, char **argv)
/* pick up args from standard input */
- initbuf = next;
initlist = ARGV;
initsize = linesize;
+ lastarg[0] = '\0';
- while (OK && MORE) {
+ while (OK) {
N_args = 0;
N_lines = 0;
- next = initbuf;
ARGV = initlist;
linesize = initsize;
- if (*lastarg) {
- *ARGV++ = addarg(lastarg);
- lastarg = "";
- }
+ next = argbuf;
+
+ while (MORE || (lastarg[0] != '\0')) {
+ int l;
+
+ if (*lastarg != '\0') {
+ arg = strcpy(next, lastarg);
+ *lastarg = '\0';
+ } else if ((arg = getarg(next)) == NULL) {
+ break;
+ }
+
+ l = strlen(arg) + 1;
+ linesize += l;
+ next += l;
+
+ /* Inserts are handled specially later. */
+ if ((n_inserts == 0) && (linesize >= BUFLIM)) {
+ /*
+ * Legal indicates hard fail if the list is
+ * truncated due to size. So fail, or if we
+ * cannot create any list because it would be
+ * too big.
+ */
+ if (LEGAL || N_args == 0) {
+ EMSG(LIST2LONG);
+ exit(2);
+ /* NOTREACHED */
+ }
+
+ /*
+ * Otherwise just save argument for later.
+ */
+ (void) strcpy(lastarg, arg);
+ break;
+ }
+
+ *ARGV++ = arg;
+
+ N_args++;
+
+ if ((PER_LINE && N_lines >= PER_LINE) ||
+ (N_ARGS && (N_args) >= N_ARGS)) {
+ break;
+ }
+
- while (((*ARGV++ = getarg()) != NULL) && OK) {
if ((ARGV - arglist) == MAXARGS) {
- save_index = ARGV - arglist;
break;
}
}
- if ((save_index == MAXARGS) && !MORE && (N_args == 0)) {
- /* there were no more args after filling arglist */
+
+ *ARGV = NULL;
+ if (N_args == 0) {
+ /* Reached the end with no more work. */
exit(exitstat);
}
/* insert arg if requested */
if (!ERR && INSERT) {
- if ((!MORE) && (N_lines == 0)) {
- exit(exitstat);
- }
- /* no more input lines */
+
p_ibuf = ins_buf;
ARGV--;
j = ibufsize = 0;
@@ -404,31 +451,22 @@ main(int argc, char **argv)
break;
}
}
- *ARGV = 0;
+ *ARGV = NULL;
if (n_inserts > 0) {
- int t_ninserts;
-
/*
* if we've done any insertions, re-calculate the
* linesize. bomb out if we've exceeded our length.
*/
- t_ninserts = n_inserts;
- n_inserts = 0; /* inserts have been done */
- linesize = 0; /* recalculate this */
-
- /* for each current argument in the list: */
+ linesize = 0;
for (ARGV = arglist; *ARGV != NULL; ARGV++) {
- /* recalculate everything. */
- if (checklen(*ARGV) != 0) {
- if (N_ARGS && (N_args >= N_ARGS)) {
- N_lines = N_args = 0;
- OK = FALSE;
- ERR = TRUE;
- }
- }
+ linesize += strlen(*ARGV) + 1;
+ }
+ if (linesize >= BUFLIM) {
+ EMSG(LIST2LONG);
+ exit(2);
+ /* NOTREACHED */
}
- n_inserts = t_ninserts;
}
/* exec command */
@@ -446,333 +484,160 @@ main(int argc, char **argv)
* so if we have a non-zero status here,
* quit immediately.
*/
- if ((exitstat |= lcall(cmdname, arglist)) == 0)
- continue;
+ exitstat |= lcall(cmdname, arglist);
}
}
}
- (void) lseek(0, file_offset, SEEK_SET);
- if (OK) {
+ if (OK)
return (exitstat);
- } else {
- /*
- * if exitstat was set, to match XCU4 complience,
- * return that value, otherwise, return 1.
- */
- return (exitstat ? exitstat : 1);
- }
-}
-
-static void
-queue(char *buffer, int len, int where)
-{
- pio *new, *element;
- if ((new = malloc(sizeof (pio))) == NULL) {
- perror(gettext("xargs: Memory allocation failure"));
- exit(1);
- }
- new->cur = new->start = buffer;
- new->length = len;
-
- if (where == TAIL) {
- new->next = NULL;
- if (queued_data == NULL) {
- queued_data = new;
- } else {
- element = queued_data;
- while (element->next != NULL) {
- element = element->next;
- }
- element->next = new;
- }
- } else {
- file_offset -= len;
- new->next = queued_data;
- queued_data = new;
- }
-}
-
-static char *
-checklen(char *arg)
-{
- int oklen;
-
- oklen = TRUE;
- linesize += strlen(arg) + 1;
- if (linesize >= BUFLIM) {
- /*
- * we skip this if there're inserts. we'll handle the
- * argument counting after all the insertions have
- * been done.
- */
- if (n_inserts == 0) {
- lastarg = arg;
- oklen = OK = FALSE;
-
- if (LEGAL) {
- ERR = TRUE;
- ermsg(gettext("arg list too long\n"));
- } else if (N_args > 1) {
- N_args = 1;
- } else {
- ermsg(gettext("a single arg was greater than "
- "the max arglist size of %d characters\n"),
- BUFLIM);
- ERR = TRUE;
- }
- }
- }
- return (oklen ? arg : 0);
+ /*
+ * if exitstat was set, to match XCU4 complience,
+ * return that value, otherwise, return 1.
+ */
+ return (exitstat ? exitstat : 1);
}
static char *
addarg(char *arg)
{
- if (checklen(arg) != 0) {
- (void) strcpy(next, arg);
- arg = next;
- next += strlen(arg) + 1;
- return (arg);
- }
- return ((char *)0);
+ linesize += (strlen(arg) + 1);
+ return (arg);
}
-/*
- * store_wchr() : append a wchar_t to a char buffer, resize buffer if required.
- *
- * Given a pointer to the beginning of a string buffer, the length of the
- * buffer and an offset indicating the next place to write within that
- * buffer, the passed wchar_t will be appended to the buffer if there is
- * enough space. If there is not enough space, an attempt to reallocate the
- * buffer will be made and if successful the passed pointer and size will be
- * updated to describe the reallocated block. Returns the new value for
- * 'offset' (it will be incremented by the number of bytes written).
- */
-static size_t
-store_wchr(char **buffer, size_t *buflen, size_t offset, wchar_t c)
-{
- int bytes;
-
- /*
- * Make sure that there is enough room in the buffer to store the
- * maximum length of c.
- */
- if ((offset + MB_CUR_MAX) > *buflen) {
- /*
- * Not enough room so attempt to reallocate. Add 'MB_CUR_MAX' to
- * buffer length to ensure that there is always enough room to
- * store 'c' if realloc succeeds, no matter what QBUF_INC is
- * defined as.
- */
- *buflen += (QBUF_INC + MB_CUR_MAX);
- if ((*buffer = realloc(*buffer, *buflen)) == NULL) {
- perror(gettext("xargs: Memory allocation failure"));
- exit(1);
- }
- }
- /* store bytes from wchar into buffer */
- bytes = wctomb(*buffer + offset, c);
- if (bytes == -1) {
- /* char was invalid */
- bytes = 1;
- *(*buffer + offset) = (char)c;
- }
- /* return new value for offset */
- return (offset + bytes);
+static void
+store_str(char **buffer, char *str, size_t len)
+{
+ (void) memcpy(*buffer, str, len);
+ (*buffer)[len] = '\0';
+ *buffer += len;
}
+
static char *
-getarg()
+getarg(char *arg)
{
- int bytes;
+ char *xarg = arg;
wchar_t c;
- char *arg;
- char *retarg, *requeue_buf;
- size_t requeue_offset = 0, requeue_len;
char mbc[MB_LEN_MAX];
+ size_t len;
+ int escape = 0;
+ int inquote = 0;
- while (iswspace(c = getwchr()) || c == '\n')
- ;
+ arg[0] = '\0';
- if (c == '\0') {
- MORE = FALSE;
- return (0);
- }
+ while (MORE) {
- /*
- * While we are reading in an argument, it is possible that we will
- * reach the maximum length of the overflow buffer and we'll have to
- * requeue what we have read so far. To handle this we allocate an
- * initial buffer here which will keep an unprocessed copy of the data
- * that we read in (this buffer will grow as required).
- */
- requeue_len = (size_t)QBUF_STARTLEN;
- if ((requeue_buf = (char *)malloc(requeue_len)) == NULL) {
- perror(gettext("xargs: Memory allocation failure"));
- exit(1);
- }
-
- for (arg = next; ; c = getwchr()) {
- bytes = wctomb(mbc, c);
-
- /*
- * Store the char that we have read before processing it in case
- * the current argument needs to be requeued.
- */
- requeue_offset = store_wchr(&requeue_buf, &requeue_len,
- requeue_offset, c);
+ len = 0;
+ c = getwchr(mbc, &len);
- /* Check for overflow the input buffer */
- if ((next + ((bytes == -1) ? 1 : bytes)) >= &argbuf[BUFLIM]) {
- /*
- * It's only an error if there are no Args in buffer
- * already.
- */
- if ((N_ARGS || PER_LINE) && LEGAL) {
- ERR = TRUE;
- ermsg(gettext("Argument list too long\n"));
- free(requeue_buf);
- return (0);
- } else if (N_args == 0) {
- lastarg = "";
- ERR = TRUE;
- ermsg(gettext("A single arg was greater than "
- "the max arglist size of %d characters\n"),
- BUFSIZE);
- free(requeue_buf);
- return (0);
- }
- /*
- * Otherwise we put back the current argument
- * and use what we have collected so far...
- */
- queue(requeue_buf, requeue_offset, HEAD);
- /* reset inquote because we have requeued the quotes */
- inquote = 0;
+ if (((arg - xarg) + len) > BUFLIM) {
+ EMSG2(ARG2LONG, BUFLIM);
+ exit(2);
+ ERR = TRUE;
return (NULL);
}
-
- if (iswctype(c, blank) && inquote == 0) {
- if (INSERT) {
- if (bytes == -1) {
- *next++ = (char)c;
- } else {
- (void) wctomb(next, c);
- next += bytes;
- }
+ switch (c) {
+ case '\n':
+ if (ZERO) {
+ store_str(&arg, mbc, len);
continue;
}
+ /* FALLTHRU */
- /* skip over trailing whitespace till next arg */
- while (iswctype((c = getwchr()), blank) &&
- (c != '\n') && (c != '\0'))
- ;
+ case '\0':
+ case WEOF: /* Note WEOF == EOF */
- /*
- * if there was space till end of line then the last
- * character was really a newline...
- */
- if (c == L'\n' || c == L'\0') {
- ungetwchr(L'\n');
- } else {
- /* later code needs to know this was a space */
- ungetwchr(c);
- c = L' ';
+ if (escape) {
+ EMSG(BADESCAPE);
+ ERR = TRUE;
+ return (NULL);
}
- goto end_arg;
- }
- switch (c) {
- case L'\0':
- case L'\n':
if (inquote) {
- *next++ = '\0';
- ermsg(gettext("Missing quote: %s\n"), arg);
+ EMSG(MISSQUOTE);
ERR = TRUE;
- free(requeue_buf);
- return (0);
+ return (NULL);
}
N_lines++;
-end_arg: *next++ = '\0';
- /* we finished without requeuing so free requeue_buf */
- free(requeue_buf);
- if ((strcmp(arg, LEOF) == 0 && *LEOF != '\0') ||
- (c == '\0' && strlen(arg) == 0)) {
- MORE = FALSE;
- /* absorb the rest of the line */
- if ((c != '\n') && (c != '\0'))
- while (c = getwchr())
- if ((c == '\n') || (c == '\0'))
- break;
- if (strcmp(arg, LEOF) == 0 && *LEOF != '\0') {
- /*
- * Encountered EOF string.
- * Don't read any more lines.
- */
- N_lines = 0;
- }
- return (0);
- } else {
- ++N_args;
- if (retarg = checklen(arg)) {
- if ((PER_LINE &&
- N_lines >= PER_LINE &&
- (c == '\0' || c == '\n')) ||
- (N_ARGS && N_args >= N_ARGS)) {
- N_lines = N_args = 0;
- lastarg = "";
- OK = FALSE;
- }
- }
- return (retarg);
- }
+ break;
case '"':
- if (inquote == 1) /* in single quoted string */
- goto is_default;
- if (inquote == 2) /* terminating double quote */
+ if (ZERO || escape || (inquote == 1)) {
+ /* treat it literally */
+ escape = 0;
+ store_str(&arg, mbc, len);
+
+ } else if (inquote == 2) {
+ /* terminating double quote */
inquote = 0;
- else /* starting quoted string */
+
+ } else {
+ /* starting quoted string */
inquote = 2;
- break;
+ }
+ continue;
case '\'':
- if (inquote == 2) /* in double quoted string */
- goto is_default;
- if (inquote == 1) /* terminating single quote */
+ if (ZERO || escape || (inquote == 2)) {
+ /* treat it literally */
+ escape = 0;
+ store_str(&arg, mbc, len);
+
+ } else if (inquote == 1) {
+ /* terminating single quote */
inquote = 0;
- else /* starting quoted string */
+
+ } else {
+ /* starting quoted string */
inquote = 1;
- break;
+ }
+ continue;
- case L'\\':
+ case '\\':
/*
* Any unquoted character can be escaped by
* preceding it with a backslash.
*/
- if (inquote == 0) {
- c = getwchr();
- /* store quoted char for potential requeueing */
- requeue_offset = store_wchr(&requeue_buf,
- &requeue_len, requeue_offset, c);
+ if (ZERO || inquote || escape) {
+ escape = 0;
+ store_str(&arg, mbc, len);
+ } else {
+ escape = 1;
}
+ continue;
default:
-is_default: if (bytes == -1) {
- *next++ = (char)c;
- } else {
- (void) wctomb(next, c);
- next += bytes;
+ /* most times we will just want to store it */
+ if (inquote || escape || ZERO || !iswctype(c, blank)) {
+ escape = 0;
+ store_str(&arg, mbc, len);
+ continue;
}
+ /* unquoted blank */
break;
}
+
+ /*
+ * At this point we are processing a complete argument.
+ */
+ if (strcmp(xarg, LEOF) == 0 && *LEOF != '\0') {
+ MORE = FALSE;
+ return (NULL);
+ }
+ if (c == WEOF) {
+ MORE = FALSE;
+ }
+ if (xarg[0] == '\0')
+ continue;
+ break;
}
-}
+ return (xarg[0] == '\0' ? NULL : xarg);
+}
/*
* ermsg(): print out an error message, and indicate failure globally.
@@ -825,15 +690,6 @@ echoargs()
return (TRUE);
}
- /*
- * at this point, there may be unexpected input pending on stdin,
- * if one has used the -n flag. this presents a problem, because
- * if we simply do a read(), we'll get the extra input, instead
- * of our desired y/n input. so, we see if there's any extra
- * input, and if there is, then we will store it.
- */
- saveinput();
-
(void) write(2, "?...", 4); /* ask the user for input */
for (i = 0; i < LINE_MAX && read(PROMPT, &reply[i], 1) > 0; i++) {
@@ -873,7 +729,7 @@ insert(char *pattern, char *subst)
bufend = &buffer[MAXSBUF];
while (*++pat) {
- if (xindex(pat, INSPAT) == 0) {
+ if (strncmp(pat, INSPAT, ipatlen) == 0) {
if (pbuf + len >= bufend) {
break;
} else {
@@ -895,7 +751,7 @@ insert(char *pattern, char *subst)
ermsg(gettext("Maximum argument size with insertion via %s's "
"exceeded\n"), INSPAT);
ERR = TRUE;
- return (0);
+ return (NULL);
}
}
@@ -908,96 +764,62 @@ addibuf(struct inserts *p)
skel = p->p_skel;
sub = *ARGV;
- linesize -= strlen(skel) + 1;
newarg = insert(skel, sub);
if (ERR)
return;
- if (checklen(newarg)) {
- if ((ibufsize += (l = strlen(newarg) + 1)) > MAXIBUF) {
- ermsg(gettext("Insert buffer overflow\n"));
- ERR = TRUE;
- }
- (void) strcpy(p_ibuf, newarg);
- *(p->p_ARGV) = p_ibuf;
- p_ibuf += l;
+ l = strlen(newarg) + 1;
+ if ((ibufsize += l) > MAXIBUF) {
+ EMSG(IBUFOVERFLOW);
+ ERR = TRUE;
}
+ (void) strcpy(p_ibuf, newarg);
+ *(p->p_ARGV) = p_ibuf;
+ p_ibuf += l;
}
/*
- * getchr(): get the next character.
+ * getwchr(): get the next wide character.
* description:
- * we get the next character from pio.structure, if there's a character
- * to get. this may happen when we've had to flush stdin=/dev/tty,
- * but still wanted to preserve the characters for later processing.
- *
- * otherwise we just get the character from stdin.
+ * we get the next character from stdin. This returns WEOF if no
+ * character is present. If ZERO is set, it gets a single byte instead
+ * a wide character.
*/
-static int
-getchr(void)
+static wint_t
+getwchr(char *mbc, size_t *sz)
{
- char c;
-
- do {
- if (queued_data == NULL) {
- char *buffer;
- int len;
-
- if ((buffer = malloc(BUFSIZE)) == NULL) {
- perror(gettext(
- "xargs: Memory allocation failure"));
- exit(1);
- }
-
- if ((len = read(0, buffer, BUFSIZE)) == 0)
- return (0);
- if (len == -1) {
- perror(gettext("xargs: Read failure"));
- exit(1);
- }
-
- queue(buffer, len, TAIL);
- }
-
- file_offset++;
- c = *queued_data->cur++; /* get the next character */
- if (--queued_data->length == 0) { /* at the end of buffer? */
- pio *nxt = queued_data->next;
+ size_t i;
+ int c;
+ wchar_t wch;
- free(queued_data->start);
- free(queued_data);
- queued_data = nxt;
- }
- } while (c == '\0');
- return (c);
-}
+ i = 0;
+ while (i < MB_CUR_MAX) {
+ if ((c = fgetc(stdin)) == EOF) {
-static wchar_t
-getwchr(void)
-{
- int i;
- wchar_t wch;
- unsigned char buffer[MB_LEN_MAX + 1];
-
- for (i = 0; i < (int)MB_CUR_MAX; ) {
- if ((buffer[i++] = getchr()) == NULL) {
- /* We have reached EOF */
- if (i == 1) {
+ if (i == 0) {
/* TRUE EOF has been reached */
- return (NULL);
+ return (WEOF);
}
+
/*
* We have some characters in our buffer still so it
* must be an invalid character right before EOF.
*/
break;
}
+ mbc[i++] = (char)c;
/* If this succeeds then we are done */
- if (mbtowc(&wch, (char *)buffer, i) != -1)
- return (wch);
+ if (ZERO) {
+ *sz = i;
+ return ((char)c);
+ }
+ if (mbtowc(&wch, mbc, i) != -1) {
+ *sz = i;
+ return ((wint_t)wch);
+ }
}
/*
@@ -1009,67 +831,50 @@ getwchr(void)
* generated in another locale?
*/
errno = EILSEQ;
- perror(gettext("xargs: Corrupt input file"));
+ PERR(CORRUPTFILE);
exit(1);
/* NOTREACHED */
}
-static void
-ungetwchr(wchar_t wch)
-{
- char *buffer;
- int bytes;
-
- if ((buffer = malloc(MB_LEN_MAX)) == NULL) {
- perror(gettext("xargs: Memory allocation failure"));
- exit(1);
- }
- bytes = wctomb(buffer, wch);
- queue(buffer, bytes, HEAD);
-}
-
-
static int
lcall(char *sub, char **subargs)
{
int retcode, retry = 0;
pid_t iwait, child;
- for (; ; ) {
+ for (;;) {
switch (child = fork()) {
default:
while ((iwait = wait(&retcode)) != child &&
iwait != (pid_t)-1)
;
if (iwait == (pid_t)-1) {
- perror(gettext("xargs: Wait failure"));
+ PERR(WAITFAIL);
exit(122);
/* NOTREACHED */
}
if (WIFSIGNALED(retcode)) {
- ermsg(gettext("Child killed with signal %d\n"),
- WTERMSIG(retcode));
+ EMSG2(CHILDSIG, WTERMSIG(retcode));
exit(125);
/* NOTREACHED */
}
if ((WEXITSTATUS(retcode) & 0377) == 0377) {
- ermsg(gettext("Command could not continue "
- "processing data\n"));
+ EMSG(CHILDFAIL);
exit(124);
/* NOTREACHED */
}
return (WEXITSTATUS(retcode));
case 0:
(void) execvp(sub, subargs);
- perror(gettext("xargs: Could not exec command"));
+ PERR(EXECFAIL);
if (errno == EACCES)
exit(126);
exit(127);
/* NOTREACHED */
case -1:
if (errno != EAGAIN && retry++ < FORK_RETRY) {
- perror(gettext("xargs: Could not fork child"));
+ PERR(FORKFAIL);
exit(123);
}
(void) sleep(1);
@@ -1078,41 +883,10 @@ lcall(char *sub, char **subargs)
}
-/*
- * If `s2' is a substring of `s1' return the offset of the first
- * occurrence of `s2' in `s1', else return -1.
- */
-static int
-xindex(char *as1, char *as2)
-{
- char *s1, *s2, c;
- int offset;
-
- s1 = as1;
- s2 = as2;
- c = *s2;
-
- while (*s1) {
- if (*s1++ == c) {
- offset = s1 - as1 - 1;
- s2++;
- while ((c = *s2++) == *s1++ && c)
- ;
- if (c == 0)
- return (offset);
- s1 = offset + as1 + 1;
- s2 = as2;
- c = *s2;
- }
- }
- return (-1);
-}
-
-
static void
usage()
{
- ermsg(gettext(USAGEMSG));
+ ermsg(_(USAGEMSG));
OK = FALSE;
}
@@ -1142,14 +916,14 @@ parseargs(int ac, char **av)
int cflag; /* 0 = not processing cmd arg */
if ((mav = malloc((ac * 2 + 1) * sizeof (char *))) == NULL) {
- perror(gettext("xargs: Memory allocation failure"));
+ PERR(MALLOCFAIL);
exit(1);
}
/* for each argument, see if we need to change things: */
for (i = mac = cflag = 0; (av[i] != NULL) && i < ac; i++, mac++) {
if ((mav[mac] = strdup(av[i])) == NULL) {
- perror(gettext("xargs: Memory allocation failure"));
+ PERR(MALLOCFAIL);
exit(1);
}
@@ -1187,8 +961,7 @@ process_special:
mav[++mac] = strdup(&av[i][2]);
}
if (mav[mac] == NULL) {
- perror(gettext("xargs: Memory"
- " allocation failure"));
+ PERR(MALLOCFAIL);
exit(1);
}
break;
@@ -1225,8 +998,7 @@ process_special:
++mac; /* inc to next mod'd arg */
if ((mav[mac] = strdup(&av[i][2])) ==
NULL) {
- perror(gettext("xargs: Memory"
- " allocation failure"));
+ PERR(MALLOCFAIL);
exit(1);
}
break;
@@ -1239,8 +1011,7 @@ process_special:
return;
}
if ((mav[mac] = strdup(av[i])) == NULL) {
- perror(gettext("xargs: Memory"
- " allocation failure"));
+ PERR(MALLOCFAIL);
exit(1);
}
break;
@@ -1273,63 +1044,3 @@ process_special:
mav[mac] = NULL;
}
-
-
-/*
- * saveinput(): pick up any pending input, so it can be processed later.
- *
- * description:
- * the purpose of this routine is to allow us to handle the user
- * typing in a 'y' or 'n', when there's existing characters already
- * in stdin. this happens when one gives the "-n" option along with
- * "-p". the problem occurs when the user first types in more arguments
- * than specified by the -n number. echoargs() wants to read stdin
- * in order to get the user's response, but if there's already stuff
- * there, echoargs() won't read the proper character.
- *
- * the solution provided by this routine is to pick up all characters
- * (if any), and store them for later processing.
- */
-
-void
-saveinput()
-{
- char *buffer; /* ptr to the floating data buffer */
- struct strpeek speek; /* to see what's on the queue */
- struct strpeek *ps;
-
- /* if we're not in -p mode, skip */
- if (PROMPT == -1) {
- return;
- }
-
-
- /* now see if there's any activity pending: */
- ps = &speek;
- ps->ctlbuf.maxlen = 0;
- ps->ctlbuf.len = 0;
- ps->ctlbuf.buf = NULL;
- ps->flags = 0;
- ps->databuf.maxlen = MAX_INPUT;
- ps->databuf.len = 0;
- if ((buffer = malloc((size_t)MAX_INPUT)) == NULL) {
- perror(gettext("xargs: Memory allocation failure"));
- exit(1);
- }
- ps->databuf.buf = (char *)buffer;
-
- if (ioctl(PROMPT, I_PEEK, ps) == -1) {
- perror(gettext("xargs: I_PEEK failure"));
- exit(1);
- }
-
- if (ps->databuf.len > 0) {
- int len;
-
- if ((len = read(PROMPT, buffer, ps->databuf.len)) == -1) {
- perror(gettext("xargs: read failure"));
- exit(1);
- }
- queue(buffer, len, TAIL);
- }
-}