Update Source To shell_cmds-216.60.1

This commit is contained in:
Thomas A 2023-02-19 20:54:09 -08:00
parent eecd2ebfba
commit 8700997f3f
29 changed files with 815 additions and 1408 deletions

4
.upstream_base_commits Normal file
View File

@ -0,0 +1,4 @@
xargs/pathname.h freebsd usr.bin/xargs/pathname.h 872b698bd4a1bfc0bf008c09228e6fd238809c75
xargs/strnsubst.c freebsd usr.bin/xargs/strnsubst.c 56640efcbe39386a0152f14fb18a314b85e7e014
xargs/xargs.1 freebsd usr.bin/xargs/xargs.1 7e6cabd06e6caa6a02eeb86308dc0cb3f27e10da
xargs/xargs.c freebsd usr.bin/xargs/xargs.c 872b698bd4a1bfc0bf008c09228e6fd238809c75

View File

@ -41,97 +41,142 @@ static char sccsid[] = "@(#)echo.c 8.1 (Berkeley) 5/31/93";
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/bin/echo/echo.c,v 1.18 2005/01/10 08:39:22 imp Exp $");
#include <sys/types.h>
#include <sys/uio.h>
#include <assert.h>
#include <errno.h>
#include <limits.h>
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <wchar.h>
/*
* Report an error and exit.
* Use it instead of err(3) to avoid linking-in stdio.
*/
static void
errexit(const char *prog, const char *reason)
flush_and_exit(void)
{
char *errstr = strerror(errno);
write(STDERR_FILENO, prog, strlen(prog));
write(STDERR_FILENO, ": ", 2);
write(STDERR_FILENO, reason, strlen(reason));
write(STDERR_FILENO, ": ", 2);
write(STDERR_FILENO, errstr, strlen(errstr));
write(STDERR_FILENO, "\n", 1);
exit(1);
if (fflush(stdout) != 0)
err(1, "fflush");
exit(0);
}
static char *
print_one_char(char *cur, int posix, int *bytes_len_out)
{
char *next;
wchar_t wc;
int bytes_len = mbtowc(&wc, cur, MB_CUR_MAX);
if (bytes_len <= 0) {
putchar(*cur);
bytes_len = 1;
goto out;
}
/* If this is not an escape sequence, just print the character */
if (wc != '\\') {
putwchar(wc);
goto out;
}
next = cur + bytes_len;
if (!posix) {
/* In non-POSIX mode, the only valid escape sequence is \c */
if (*next == 'c') {
flush_and_exit();
} else {
putchar(wc);
goto out;
}
} else {
cur = next;
bytes_len = 1;
}
switch (*cur) {
case 'a':
putchar('\a');
goto out;
case 'b':
putchar('\b');
goto out;
case 'c':
flush_and_exit();
case 'f':
putchar('\f');
goto out;
case 'n':
putchar('\n');
goto out;
case 'r':
putchar('\r');
goto out;
case 't':
putchar('\t');
goto out;
case 'v':
putchar('\v');
goto out;
case '\\':
putchar('\\');
goto out;
case '0': {
int j = 0, num = 0;
while ((*++cur >= '0' && *cur <= '7') &&
j++ < 3) {
num <<= 3;
num |= (*cur - '0');
}
putchar(num);
--cur;
goto out;
}
default:
--cur;
putchar(*cur);
goto out;
}
out:
if (bytes_len_out)
*bytes_len_out = bytes_len;
return cur;
}
int
main(int argc, char *argv[])
{
int nflag; /* if not set, output a trailing newline. */
int veclen; /* number of writev arguments. */
struct iovec *iov, *vp; /* Elements to write, current element. */
char space[] = " ";
char newline[] = "\n";
char *progname = argv[0];
int nflag = 0;
int posix = (getenv("POSIXLY_CORRECT") != NULL || getenv("POSIX_PEDANTIC") != NULL);
/* This utility may NOT do getopt(3) option parsing. */
if (*++argv && !strcmp(*argv, "-n")) {
++argv;
--argc;
if (!posix && argv[1] && strcmp(argv[1], "-n") == 0)
nflag = 1;
} else
nflag = 0;
veclen = (argc >= 2) ? (argc - 2) * 2 + 1 : 0;
for (int i = 0; i < argc; i++) {
/* argv[0] == progname */
int ignore_arg = (i == 0 || (i == 1 && nflag == 1));
int last_arg = (i == (argc - 1));
if (!ignore_arg) {
char *cur = argv[i];
size_t arg_len = strlen(cur);
int bytes_len = 0;
if ((vp = iov = malloc((veclen + 1) * sizeof(struct iovec))) == NULL)
errexit(progname, "malloc");
while (argv[0] != NULL) {
size_t len;
len = strlen(argv[0]);
/*
* If the next argument is NULL then this is this
* the last argument, therefore we need to check
* for a trailing \c.
*/
if (argv[1] == NULL) {
/* is there room for a '\c' and is there one? */
if (len >= 2 &&
argv[0][len - 2] == '\\' &&
argv[0][len - 1] == 'c') {
/* chop it and set the no-newline flag. */
len -= 2;
nflag = 1;
for (const char *end = cur + arg_len; cur < end; cur += bytes_len) {
cur = print_one_char(cur, posix, &bytes_len);
}
}
vp->iov_base = *argv;
vp++->iov_len = len;
if (*++argv) {
vp->iov_base = space;
vp++->iov_len = 1;
}
}
if (!nflag) {
veclen++;
vp->iov_base = newline;
vp++->iov_len = 1;
}
/* assert(veclen == (vp - iov)); */
while (veclen) {
int nwrite;
if (last_arg && !nflag)
putchar('\n');
else if (!last_arg && !ignore_arg)
putchar(' ');
nwrite = (veclen > IOV_MAX) ? IOV_MAX : veclen;
if (writev(STDOUT_FILENO, iov, nwrite) == -1)
errexit(progname, "write");
iov += nwrite;
veclen -= nwrite;
if (fflush(stdout) != 0)
err(1, "fflush");
}
return 0;
}

View File

@ -1,102 +0,0 @@
/*
* This file was generated by the mkbuiltins program.
*/
#include <stdlib.h>
#include "shell.h"
#include "builtins.h"
int (*const builtinfunc[])(int, char **) = {
bltincmd,
aliascmd,
bgcmd,
bindcmd,
breakcmd,
cdcmd,
commandcmd,
dotcmd,
echocmd,
evalcmd,
execcmd,
exitcmd,
letcmd,
exportcmd,
falsecmd,
fgcmd,
freebsd_wordexpcmd,
getoptscmd,
hashcmd,
histcmd,
jobidcmd,
jobscmd,
killcmd,
localcmd,
printfcmd,
pwdcmd,
readcmd,
returncmd,
setcmd,
setvarcmd,
shiftcmd,
testcmd,
timescmd,
trapcmd,
truecmd,
typecmd,
ulimitcmd,
umaskcmd,
unaliascmd,
unsetcmd,
waitcmd,
wordexpcmd,
};
const unsigned char builtincmd[] = {
"\007\000builtin"
"\005\001alias"
"\002\002bg"
"\004\003bind"
"\005\204break"
"\010\204continue"
"\002\005cd"
"\005\005chdir"
"\007\006command"
"\001\207."
"\004\010echo"
"\004\211eval"
"\004\212exec"
"\004\213exit"
"\003\014let"
"\006\215export"
"\010\215readonly"
"\005\016false"
"\002\017fg"
"\017\020freebsd_wordexp"
"\007\021getopts"
"\004\022hash"
"\002\023fc"
"\005\024jobid"
"\004\025jobs"
"\004\026kill"
"\005\027local"
"\006\030printf"
"\003\031pwd"
"\004\032read"
"\006\233return"
"\003\234set"
"\006\035setvar"
"\005\236shift"
"\004\037test"
"\001\037["
"\005\240times"
"\004\241trap"
"\001\242:"
"\004\042true"
"\004\043type"
"\006\044ulimit"
"\005\045umask"
"\007\046unalias"
"\005\247unset"
"\004\050wait"
"\007\051wordexp"
};

View File

@ -1,115 +0,0 @@
/*
* This file was generated by the mkbuiltins program.
*/
#include <sys/cdefs.h>
#define BLTINCMD 0
#define ALIASCMD 1
#define BGCMD 2
#define BINDCMD 3
#define BREAKCMD 4
#define CDCMD 5
#define COMMANDCMD 6
#define DOTCMD 7
#define ECHOCMD 8
#define EVALCMD 9
#define EXECCMD 10
#define EXITCMD 11
#define LETCMD 12
#define EXPORTCMD 13
#define FALSECMD 14
#define FGCMD 15
#define FREEBSD_WORDEXPCMD 16
#define GETOPTSCMD 17
#define HASHCMD 18
#define HISTCMD 19
#define JOBIDCMD 20
#define JOBSCMD 21
#define KILLCMD 22
#define LOCALCMD 23
#define PRINTFCMD 24
#define PWDCMD 25
#define READCMD 26
#define RETURNCMD 27
#define SETCMD 28
#define SETVARCMD 29
#define SHIFTCMD 30
#define TESTCMD 31
#define TIMESCMD 32
#define TRAPCMD 33
#define TRUECMD 34
#define TYPECMD 35
#define ULIMITCMD 36
#define UMASKCMD 37
#define UNALIASCMD 38
#define UNSETCMD 39
#define WAITCMD 40
#define WORDEXPCMD 41
#define BUILTIN_SPECIAL 0x80
extern int (*const builtinfunc[])(int, char **);
extern const unsigned char builtincmd[];
int bltincmd(int, char **);
int aliascmd(int, char **);
int bgcmd(int, char **);
int bindcmd(int, char **);
int breakcmd(int, char **);
int cdcmd(int, char **);
int commandcmd(int, char **);
int dotcmd(int, char **);
int echocmd(int, char **);
int evalcmd(int, char **);
int execcmd(int, char **);
int exitcmd(int, char **);
int letcmd(int, char **);
int exportcmd(int, char **);
int falsecmd(int, char **);
int fgcmd(int, char **);
int freebsd_wordexpcmd(int, char **);
int getoptscmd(int, char **);
int hashcmd(int, char **);
int histcmd(int, char **);
int jobidcmd(int, char **);
int jobscmd(int, char **);
int killcmd(int, char **);
int localcmd(int, char **);
int printfcmd(int, char **);
int pwdcmd(int, char **);
int readcmd(int, char **);
int returncmd(int, char **);
int setcmd(int, char **);
int setvarcmd(int, char **);
int shiftcmd(int, char **);
int testcmd(int, char **);
int timescmd(int, char **);
int trapcmd(int, char **);
int truecmd(int, char **);
int typecmd(int, char **);
int ulimitcmd(int, char **);
int umaskcmd(int, char **);
int unaliascmd(int, char **);
int unsetcmd(int, char **);
int waitcmd(int, char **);
int wordexpcmd(int, char **);
static inline int
safe_builtin_always(int idx)
{
if (idx == BLTINCMD ||
idx == COMMANDCMD ||
idx == ECHOCMD ||
idx == FALSECMD ||
idx == JOBIDCMD ||
idx == JOBSCMD ||
idx == KILLCMD ||
idx == PRINTFCMD ||
idx == PWDCMD ||
idx == TESTCMD ||
idx == TIMESCMD ||
idx == TRUECMD ||
idx == TYPECMD)
return (1);
return(0);
}

View File

@ -1,376 +0,0 @@
/*
* This file was generated by the mknodes program.
*/
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Kenneth Almquist.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)nodes.c.pat 8.2 (Berkeley) 5/4/95
* $FreeBSD: head/bin/sh/nodes.c.pat 314436 2017-02-28 23:42:47Z imp $
*/
#include <sys/param.h>
#include <stdlib.h>
#include <stddef.h>
/*
* Routine for dealing with parsed shell commands.
*/
#include "shell.h"
#include "nodes.h"
#include "memalloc.h"
#include "mystring.h"
struct nodesize {
int blocksize; /* size of structures in function */
int stringsize; /* size of strings in node */
};
struct nodecopystate {
pointer block; /* block to allocate function from */
char *string; /* block to allocate strings from */
};
static const short nodesize[27] = {
ALIGN(sizeof (struct nbinary)),
ALIGN(sizeof (struct ncmd)),
ALIGN(sizeof (struct npipe)),
ALIGN(sizeof (struct nredir)),
ALIGN(sizeof (struct nredir)),
ALIGN(sizeof (struct nredir)),
ALIGN(sizeof (struct nbinary)),
ALIGN(sizeof (struct nbinary)),
ALIGN(sizeof (struct nif)),
ALIGN(sizeof (struct nbinary)),
ALIGN(sizeof (struct nbinary)),
ALIGN(sizeof (struct nfor)),
ALIGN(sizeof (struct ncase)),
ALIGN(sizeof (struct nclist)),
ALIGN(sizeof (struct nclist)),
ALIGN(sizeof (struct narg)),
ALIGN(sizeof (struct narg)),
ALIGN(sizeof (struct nfile)),
ALIGN(sizeof (struct nfile)),
ALIGN(sizeof (struct nfile)),
ALIGN(sizeof (struct nfile)),
ALIGN(sizeof (struct nfile)),
ALIGN(sizeof (struct ndup)),
ALIGN(sizeof (struct ndup)),
ALIGN(sizeof (struct nhere)),
ALIGN(sizeof (struct nhere)),
ALIGN(sizeof (struct nnot)),
};
static void calcsize(union node *, struct nodesize *);
static void sizenodelist(struct nodelist *, struct nodesize *);
static union node *copynode(union node *, struct nodecopystate *);
static struct nodelist *copynodelist(struct nodelist *, struct nodecopystate *);
static char *nodesavestr(const char *, struct nodecopystate *);
struct funcdef {
unsigned int refcount;
union node n;
};
/*
* Make a copy of a parse tree.
*/
struct funcdef *
copyfunc(union node *n)
{
struct nodesize sz;
struct nodecopystate st;
struct funcdef *fn;
if (n == NULL)
return NULL;
sz.blocksize = offsetof(struct funcdef, n);
sz.stringsize = 0;
calcsize(n, &sz);
fn = ckmalloc(sz.blocksize + sz.stringsize);
fn->refcount = 1;
st.block = (char *)fn + offsetof(struct funcdef, n);
st.string = (char *)fn + sz.blocksize;
copynode(n, &st);
return fn;
}
union node *
getfuncnode(struct funcdef *fn)
{
return fn == NULL ? NULL : &fn->n;
}
static void
calcsize(union node *n, struct nodesize *result)
{
if (n == NULL)
return;
result->blocksize += nodesize[n->type];
switch (n->type) {
case NSEMI:
case NAND:
case NOR:
case NWHILE:
case NUNTIL:
calcsize(n->nbinary.ch2, result);
calcsize(n->nbinary.ch1, result);
break;
case NCMD:
calcsize(n->ncmd.redirect, result);
calcsize(n->ncmd.args, result);
break;
case NPIPE:
sizenodelist(n->npipe.cmdlist, result);
break;
case NREDIR:
case NBACKGND:
case NSUBSHELL:
calcsize(n->nredir.redirect, result);
calcsize(n->nredir.n, result);
break;
case NIF:
calcsize(n->nif.elsepart, result);
calcsize(n->nif.ifpart, result);
calcsize(n->nif.test, result);
break;
case NFOR:
result->stringsize += strlen(n->nfor.var) + 1;
calcsize(n->nfor.body, result);
calcsize(n->nfor.args, result);
break;
case NCASE:
calcsize(n->ncase.cases, result);
calcsize(n->ncase.expr, result);
break;
case NCLIST:
case NCLISTFALLTHRU:
calcsize(n->nclist.body, result);
calcsize(n->nclist.pattern, result);
calcsize(n->nclist.next, result);
break;
case NDEFUN:
case NARG:
sizenodelist(n->narg.backquote, result);
result->stringsize += strlen(n->narg.text) + 1;
calcsize(n->narg.next, result);
break;
case NTO:
case NFROM:
case NFROMTO:
case NAPPEND:
case NCLOBBER:
calcsize(n->nfile.fname, result);
calcsize(n->nfile.next, result);
break;
case NTOFD:
case NFROMFD:
calcsize(n->ndup.vname, result);
calcsize(n->ndup.next, result);
break;
case NHERE:
case NXHERE:
calcsize(n->nhere.doc, result);
calcsize(n->nhere.next, result);
break;
case NNOT:
calcsize(n->nnot.com, result);
break;
};
}
static void
sizenodelist(struct nodelist *lp, struct nodesize *result)
{
while (lp) {
result->blocksize += ALIGN(sizeof(struct nodelist));
calcsize(lp->n, result);
lp = lp->next;
}
}
static union node *
copynode(union node *n, struct nodecopystate *state)
{
union node *new;
if (n == NULL)
return NULL;
new = state->block;
state->block = (char *)state->block + nodesize[n->type];
switch (n->type) {
case NSEMI:
case NAND:
case NOR:
case NWHILE:
case NUNTIL:
new->nbinary.ch2 = copynode(n->nbinary.ch2, state);
new->nbinary.ch1 = copynode(n->nbinary.ch1, state);
break;
case NCMD:
new->ncmd.redirect = copynode(n->ncmd.redirect, state);
new->ncmd.args = copynode(n->ncmd.args, state);
break;
case NPIPE:
new->npipe.cmdlist = copynodelist(n->npipe.cmdlist, state);
new->npipe.backgnd = n->npipe.backgnd;
break;
case NREDIR:
case NBACKGND:
case NSUBSHELL:
new->nredir.redirect = copynode(n->nredir.redirect, state);
new->nredir.n = copynode(n->nredir.n, state);
break;
case NIF:
new->nif.elsepart = copynode(n->nif.elsepart, state);
new->nif.ifpart = copynode(n->nif.ifpart, state);
new->nif.test = copynode(n->nif.test, state);
break;
case NFOR:
new->nfor.var = nodesavestr(n->nfor.var, state);
new->nfor.body = copynode(n->nfor.body, state);
new->nfor.args = copynode(n->nfor.args, state);
break;
case NCASE:
new->ncase.cases = copynode(n->ncase.cases, state);
new->ncase.expr = copynode(n->ncase.expr, state);
break;
case NCLIST:
case NCLISTFALLTHRU:
new->nclist.body = copynode(n->nclist.body, state);
new->nclist.pattern = copynode(n->nclist.pattern, state);
new->nclist.next = copynode(n->nclist.next, state);
break;
case NDEFUN:
case NARG:
new->narg.backquote = copynodelist(n->narg.backquote, state);
new->narg.text = nodesavestr(n->narg.text, state);
new->narg.next = copynode(n->narg.next, state);
break;
case NTO:
case NFROM:
case NFROMTO:
case NAPPEND:
case NCLOBBER:
new->nfile.fname = copynode(n->nfile.fname, state);
new->nfile.next = copynode(n->nfile.next, state);
new->nfile.fd = n->nfile.fd;
break;
case NTOFD:
case NFROMFD:
new->ndup.vname = copynode(n->ndup.vname, state);
new->ndup.dupfd = n->ndup.dupfd;
new->ndup.next = copynode(n->ndup.next, state);
new->ndup.fd = n->ndup.fd;
break;
case NHERE:
case NXHERE:
new->nhere.doc = copynode(n->nhere.doc, state);
new->nhere.next = copynode(n->nhere.next, state);
new->nhere.fd = n->nhere.fd;
break;
case NNOT:
new->nnot.com = copynode(n->nnot.com, state);
break;
};
new->type = n->type;
return new;
}
static struct nodelist *
copynodelist(struct nodelist *lp, struct nodecopystate *state)
{
struct nodelist *start;
struct nodelist **lpp;
lpp = &start;
while (lp) {
*lpp = state->block;
state->block = (char *)state->block +
ALIGN(sizeof(struct nodelist));
(*lpp)->n = copynode(lp->n, state);
lp = lp->next;
lpp = &(*lpp)->next;
}
*lpp = NULL;
return start;
}
static char *
nodesavestr(const char *s, struct nodecopystate *state)
{
const char *p = s;
char *q = state->string;
char *rtn = state->string;
while ((*q++ = *p++) != '\0')
continue;
state->string = q;
return rtn;
}
void
reffunc(struct funcdef *fn)
{
if (fn)
fn->refcount++;
}
/*
* Decrement the reference count of a function definition, freeing it
* if it falls to 0.
*/
void
unreffunc(struct funcdef *fn)
{
if (fn) {
fn->refcount--;
if (fn->refcount > 0)
return;
ckfree(fn);
}
}

View File

@ -1,163 +0,0 @@
/*
* This file was generated by the mknodes program.
*/
#define NSEMI 0
#define NCMD 1
#define NPIPE 2
#define NREDIR 3
#define NBACKGND 4
#define NSUBSHELL 5
#define NAND 6
#define NOR 7
#define NIF 8
#define NWHILE 9
#define NUNTIL 10
#define NFOR 11
#define NCASE 12
#define NCLIST 13
#define NCLISTFALLTHRU 14
#define NDEFUN 15
#define NARG 16
#define NTO 17
#define NFROM 18
#define NFROMTO 19
#define NAPPEND 20
#define NCLOBBER 21
#define NTOFD 22
#define NFROMFD 23
#define NHERE 24
#define NXHERE 25
#define NNOT 26
struct nbinary {
int type;
union node *ch1;
union node *ch2;
};
struct ncmd {
int type;
union node *args;
union node *redirect;
};
struct npipe {
int type;
int backgnd;
struct nodelist *cmdlist;
};
struct nredir {
int type;
union node *n;
union node *redirect;
};
struct nif {
int type;
union node *test;
union node *ifpart;
union node *elsepart;
};
struct nfor {
int type;
union node *args;
union node *body;
char *var;
};
struct ncase {
int type;
union node *expr;
union node *cases;
};
struct nclist {
int type;
union node *next;
union node *pattern;
union node *body;
};
struct narg {
int type;
union node *next;
char *text;
struct nodelist *backquote;
};
struct nfile {
int type;
int fd;
union node *next;
union node *fname;
char *expfname;
};
struct ndup {
int type;
int fd;
union node *next;
int dupfd;
union node *vname;
};
struct nhere {
int type;
int fd;
union node *next;
union node *doc;
const char *expdoc;
};
struct nnot {
int type;
union node *com;
};
union node {
int type;
struct nbinary nbinary;
struct ncmd ncmd;
struct npipe npipe;
struct nredir nredir;
struct nif nif;
struct nfor nfor;
struct ncase ncase;
struct nclist nclist;
struct narg narg;
struct nfile nfile;
struct ndup ndup;
struct nhere nhere;
struct nnot nnot;
};
struct nodelist {
struct nodelist *next;
union node *n;
};
struct funcdef;
struct funcdef *copyfunc(union node *);
union node *getfuncnode(struct funcdef *);
void reffunc(struct funcdef *);
void unreffunc(struct funcdef *);

View File

@ -1,192 +0,0 @@
/*
* This file was generated by the mksyntax program.
*/
#include "parser.h"
#include "shell.h"
#include "syntax.h"
/* syntax table used when not in quotes */
const char basesyntax[SYNBASE + CHAR_MAX + 1] = {
[SYNBASE + PEOF] = CEOF,
[SYNBASE + CTLESC] = CCTL,
[SYNBASE + CTLVAR] = CCTL,
[SYNBASE + CTLENDVAR] = CCTL,
[SYNBASE + CTLBACKQ] = CCTL,
[SYNBASE + CTLBACKQ + CTLQUOTE] = CCTL,
[SYNBASE + CTLARI] = CCTL,
[SYNBASE + CTLENDARI] = CCTL,
[SYNBASE + CTLQUOTEMARK] = CCTL,
[SYNBASE + CTLQUOTEEND] = CCTL,
[SYNBASE + '\n'] = CNL,
[SYNBASE + '\\'] = CBACK,
[SYNBASE + '\''] = CSQUOTE,
[SYNBASE + '"'] = CDQUOTE,
[SYNBASE + '`'] = CBQUOTE,
[SYNBASE + '$'] = CVAR,
[SYNBASE + '}'] = CENDVAR,
[SYNBASE + '<'] = CSPCL,
[SYNBASE + '>'] = CSPCL,
[SYNBASE + '('] = CSPCL,
[SYNBASE + ')'] = CSPCL,
[SYNBASE + ';'] = CSPCL,
[SYNBASE + '&'] = CSPCL,
[SYNBASE + '|'] = CSPCL,
[SYNBASE + ' '] = CSPCL,
[SYNBASE + '\t'] = CSPCL,
};
/* syntax table used when in double quotes */
const char dqsyntax[SYNBASE + CHAR_MAX + 1] = {
[SYNBASE + PEOF] = CEOF,
[SYNBASE + CTLESC] = CCTL,
[SYNBASE + CTLVAR] = CCTL,
[SYNBASE + CTLENDVAR] = CCTL,
[SYNBASE + CTLBACKQ] = CCTL,
[SYNBASE + CTLBACKQ + CTLQUOTE] = CCTL,
[SYNBASE + CTLARI] = CCTL,
[SYNBASE + CTLENDARI] = CCTL,
[SYNBASE + CTLQUOTEMARK] = CCTL,
[SYNBASE + CTLQUOTEEND] = CCTL,
[SYNBASE + '\n'] = CNL,
[SYNBASE + '\\'] = CBACK,
[SYNBASE + '"'] = CENDQUOTE,
[SYNBASE + '`'] = CBQUOTE,
[SYNBASE + '$'] = CVAR,
[SYNBASE + '}'] = CENDVAR,
[SYNBASE + '!'] = CCTL,
[SYNBASE + '*'] = CCTL,
[SYNBASE + '?'] = CCTL,
[SYNBASE + '['] = CCTL,
[SYNBASE + ']'] = CCTL,
[SYNBASE + '='] = CCTL,
[SYNBASE + '~'] = CCTL,
[SYNBASE + ':'] = CCTL,
[SYNBASE + '/'] = CCTL,
[SYNBASE + '-'] = CCTL,
[SYNBASE + '^'] = CCTL,
};
/* syntax table used when in single quotes */
const char sqsyntax[SYNBASE + CHAR_MAX + 1] = {
[SYNBASE + PEOF] = CEOF,
[SYNBASE + CTLESC] = CCTL,
[SYNBASE + CTLVAR] = CCTL,
[SYNBASE + CTLENDVAR] = CCTL,
[SYNBASE + CTLBACKQ] = CCTL,
[SYNBASE + CTLBACKQ + CTLQUOTE] = CCTL,
[SYNBASE + CTLARI] = CCTL,
[SYNBASE + CTLENDARI] = CCTL,
[SYNBASE + CTLQUOTEMARK] = CCTL,
[SYNBASE + CTLQUOTEEND] = CCTL,
[SYNBASE + '\n'] = CNL,
[SYNBASE + '\\'] = CSBACK,
[SYNBASE + '\''] = CENDQUOTE,
[SYNBASE + '!'] = CCTL,
[SYNBASE + '*'] = CCTL,
[SYNBASE + '?'] = CCTL,
[SYNBASE + '['] = CCTL,
[SYNBASE + ']'] = CCTL,
[SYNBASE + '='] = CCTL,
[SYNBASE + '~'] = CCTL,
[SYNBASE + ':'] = CCTL,
[SYNBASE + '/'] = CCTL,
[SYNBASE + '-'] = CCTL,
[SYNBASE + '^'] = CCTL,
};
/* syntax table used when in arithmetic */
const char arisyntax[SYNBASE + CHAR_MAX + 1] = {
[SYNBASE + PEOF] = CEOF,
[SYNBASE + CTLESC] = CCTL,
[SYNBASE + CTLVAR] = CCTL,
[SYNBASE + CTLENDVAR] = CCTL,
[SYNBASE + CTLBACKQ] = CCTL,
[SYNBASE + CTLBACKQ + CTLQUOTE] = CCTL,
[SYNBASE + CTLARI] = CCTL,
[SYNBASE + CTLENDARI] = CCTL,
[SYNBASE + CTLQUOTEMARK] = CCTL,
[SYNBASE + CTLQUOTEEND] = CCTL,
[SYNBASE + '\n'] = CNL,
[SYNBASE + '\\'] = CBACK,
[SYNBASE + '`'] = CBQUOTE,
[SYNBASE + '"'] = CIGN,
[SYNBASE + '$'] = CVAR,
[SYNBASE + '}'] = CENDVAR,
[SYNBASE + '('] = CLP,
[SYNBASE + ')'] = CRP,
};
/* character classification table */
const char is_type[SYNBASE + CHAR_MAX + 1] = {
[SYNBASE + '0'] = ISDIGIT,
[SYNBASE + '1'] = ISDIGIT,
[SYNBASE + '2'] = ISDIGIT,
[SYNBASE + '3'] = ISDIGIT,
[SYNBASE + '4'] = ISDIGIT,
[SYNBASE + '5'] = ISDIGIT,
[SYNBASE + '6'] = ISDIGIT,
[SYNBASE + '7'] = ISDIGIT,
[SYNBASE + '8'] = ISDIGIT,
[SYNBASE + '9'] = ISDIGIT,
[SYNBASE + 'a'] = ISLOWER,
[SYNBASE + 'b'] = ISLOWER,
[SYNBASE + 'c'] = ISLOWER,
[SYNBASE + 'd'] = ISLOWER,
[SYNBASE + 'e'] = ISLOWER,
[SYNBASE + 'f'] = ISLOWER,
[SYNBASE + 'g'] = ISLOWER,
[SYNBASE + 'h'] = ISLOWER,
[SYNBASE + 'i'] = ISLOWER,
[SYNBASE + 'j'] = ISLOWER,
[SYNBASE + 'k'] = ISLOWER,
[SYNBASE + 'l'] = ISLOWER,
[SYNBASE + 'm'] = ISLOWER,
[SYNBASE + 'n'] = ISLOWER,
[SYNBASE + 'o'] = ISLOWER,
[SYNBASE + 'p'] = ISLOWER,
[SYNBASE + 'q'] = ISLOWER,
[SYNBASE + 'r'] = ISLOWER,
[SYNBASE + 's'] = ISLOWER,
[SYNBASE + 't'] = ISLOWER,
[SYNBASE + 'u'] = ISLOWER,
[SYNBASE + 'v'] = ISLOWER,
[SYNBASE + 'w'] = ISLOWER,
[SYNBASE + 'x'] = ISLOWER,
[SYNBASE + 'y'] = ISLOWER,
[SYNBASE + 'z'] = ISLOWER,
[SYNBASE + 'A'] = ISUPPER,
[SYNBASE + 'B'] = ISUPPER,
[SYNBASE + 'C'] = ISUPPER,
[SYNBASE + 'D'] = ISUPPER,
[SYNBASE + 'E'] = ISUPPER,
[SYNBASE + 'F'] = ISUPPER,
[SYNBASE + 'G'] = ISUPPER,
[SYNBASE + 'H'] = ISUPPER,
[SYNBASE + 'I'] = ISUPPER,
[SYNBASE + 'J'] = ISUPPER,
[SYNBASE + 'K'] = ISUPPER,
[SYNBASE + 'L'] = ISUPPER,
[SYNBASE + 'M'] = ISUPPER,
[SYNBASE + 'N'] = ISUPPER,
[SYNBASE + 'O'] = ISUPPER,
[SYNBASE + 'P'] = ISUPPER,
[SYNBASE + 'Q'] = ISUPPER,
[SYNBASE + 'R'] = ISUPPER,
[SYNBASE + 'S'] = ISUPPER,
[SYNBASE + 'T'] = ISUPPER,
[SYNBASE + 'U'] = ISUPPER,
[SYNBASE + 'V'] = ISUPPER,
[SYNBASE + 'W'] = ISUPPER,
[SYNBASE + 'X'] = ISUPPER,
[SYNBASE + 'Y'] = ISUPPER,
[SYNBASE + 'Z'] = ISUPPER,
[SYNBASE + '_'] = ISUNDER,
[SYNBASE + '#'] = ISSPECL,
[SYNBASE + '?'] = ISSPECL,
[SYNBASE + '$'] = ISSPECL,
[SYNBASE + '!'] = ISSPECL,
[SYNBASE + '-'] = ISSPECL,
[SYNBASE + '*'] = ISSPECL,
[SYNBASE + '@'] = ISSPECL,
};

View File

@ -1,54 +0,0 @@
/*
* This file was generated by the mksyntax program.
*/
#include <sys/cdefs.h>
#include <limits.h>
/* Syntax classes */
#define CWORD 0 /* character is nothing special */
#define CNL 1 /* newline character */
#define CBACK 2 /* a backslash character */
#define CSBACK 3 /* a backslash character in single quotes */
#define CSQUOTE 4 /* single quote */
#define CDQUOTE 5 /* double quote */
#define CENDQUOTE 6 /* a terminating quote */
#define CBQUOTE 7 /* backwards single quote */
#define CVAR 8 /* a dollar sign */
#define CENDVAR 9 /* a '}' character */
#define CLP 10 /* a left paren in arithmetic */
#define CRP 11 /* a right paren in arithmetic */
#define CEOF 12 /* end of file */
#define CCTL 13 /* like CWORD, except it must be escaped */
#define CSPCL 14 /* these terminate a word */
#define CIGN 15 /* character should be ignored */
/* Syntax classes for is_ functions */
#define ISDIGIT 01 /* a digit */
#define ISUPPER 02 /* an upper case letter */
#define ISLOWER 04 /* a lower case letter */
#define ISUNDER 010 /* an underscore */
#define ISSPECL 020 /* the name of a special parameter */
#define SYNBASE (1 - CHAR_MIN)
#define PEOF -SYNBASE
#define BASESYNTAX (basesyntax + SYNBASE)
#define DQSYNTAX (dqsyntax + SYNBASE)
#define SQSYNTAX (sqsyntax + SYNBASE)
#define ARISYNTAX (arisyntax + SYNBASE)
#define is_digit(c) ((unsigned int)((c) - '0') <= 9)
#define is_eof(c) ((c) == PEOF)
#define is_alpha(c) ((is_type+SYNBASE)[(int)c] & (ISUPPER|ISLOWER))
#define is_name(c) ((is_type+SYNBASE)[(int)c] & (ISUPPER|ISLOWER|ISUNDER))
#define is_in_name(c) ((is_type+SYNBASE)[(int)c] & (ISUPPER|ISLOWER|ISUNDER|ISDIGIT))
#define is_special(c) ((is_type+SYNBASE)[(int)c] & (ISSPECL|ISDIGIT))
#define digit_val(c) ((c) - '0')
extern const char basesyntax[];
extern const char dqsyntax[];
extern const char sqsyntax[];
extern const char arisyntax[];
extern const char is_type[];

View File

@ -1,112 +0,0 @@
#define TEOF 0
#define TNL 1
#define TSEMI 2
#define TBACKGND 3
#define TAND 4
#define TOR 5
#define TPIPE 6
#define TLP 7
#define TRP 8
#define TENDCASE 9
#define TFALLTHRU 10
#define TREDIR 11
#define TWORD 12
#define TIF 13
#define TTHEN 14
#define TELSE 15
#define TELIF 16
#define TFI 17
#define TWHILE 18
#define TUNTIL 19
#define TFOR 20
#define TDO 21
#define TDONE 22
#define TBEGIN 23
#define TEND 24
#define TCASE 25
#define TESAC 26
#define TNOT 27
/* Array indicating which tokens mark the end of a list */
static const char tokendlist[] = {
1,
0,
0,
0,
0,
0,
0,
0,
1,
1,
1,
0,
0,
0,
1,
1,
1,
1,
0,
0,
0,
1,
1,
0,
1,
0,
1,
0,
};
static const char *const tokname[] = {
"end of file",
"newline",
"\";\"",
"\"&\"",
"\"&&\"",
"\"||\"",
"\"|\"",
"\"(\"",
"\")\"",
"\";;\"",
"\";&\"",
"redirection",
"word",
"\"if\"",
"\"then\"",
"\"else\"",
"\"elif\"",
"\"fi\"",
"\"while\"",
"\"until\"",
"\"for\"",
"\"do\"",
"\"done\"",
"\"{\"",
"\"}\"",
"\"case\"",
"\"esac\"",
"\"!\"",
};
#define KWDOFFSET 13
const char *const parsekwd[] = {
"if",
"then",
"else",
"elif",
"fi",
"while",
"until",
"for",
"do",
"done",
"{",
"}",
"case",
"esac",
"!",
0
};

View File

@ -62,6 +62,7 @@ static void nosig(const char *);
static void printsignals(FILE *);
static int signame_to_signum(const char *);
static void usage(void);
static void print_signum(int, FILE *, char);
#ifdef __APPLE__
#define sys_nsig NSIG
@ -93,7 +94,7 @@ main(int argc, char *argv[])
numsig -= 128;
if (numsig <= 0 || numsig >= sys_nsig)
nosig(*argv);
printf("%s\n", sys_signame[numsig]);
print_signum(numsig, stdout, '\n');
return (0);
}
printsignals(stdout);
@ -155,6 +156,23 @@ main(int argc, char *argv[])
return (errors);
}
static void
print_signum(int numsig, FILE *fp, char separator)
{
char *signame;
int i;
signame = strdup(sys_signame[numsig]);
for(i = 0; signame[i] != '\0'; i++) {
char upper = toupper(signame[i]);
signame[i] = upper;
}
fprintf(fp, "%s%c", signame, separator);
free(signame);
}
static int
signame_to_signum(const char *sig)
{
@ -188,11 +206,10 @@ printsignals(FILE *fp)
int n;
for (n = 1; n < sys_nsig; n++) {
(void)fprintf(fp, "%s", sys_signame[n]);
char sep = ' ';
if (n == (sys_nsig / 2) || n == (sys_nsig - 1))
(void)fprintf(fp, "\n");
else
(void)fprintf(fp, " ");
sep = '\n';
print_signum(n, fp, sep);
}
}

View File

@ -12,7 +12,7 @@
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 4. Neither the name of the University nor the names of its contributors
.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
@ -29,9 +29,9 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)printf.1 8.1 (Berkeley) 6/6/93
.\" $FreeBSD: head/usr.bin/printf/printf.1 264743 2014-04-21 22:47:18Z pfg $
.\" $FreeBSD$
.\"
.Dd April 21, 2014
.Dd July 1, 2020
.Dt PRINTF 1
.Os
.Sh NAME
@ -87,8 +87,6 @@ are as follows:
Write a <bell> character.
.It Cm \eb
Write a <backspace> character.
.It Cm \ec
Ignore remaining characters in this string.
.It Cm \ef
Write a <form-feed> character.
.It Cm \en
@ -289,7 +287,12 @@ The permitted escape sequences are slightly different in that
octal escapes are
.Cm \e0 Ns Ar num
instead of
.Cm \e Ns Ar num .
.Cm \e Ns Ar num
and that an additional escape sequence
.Cm \ec
stops further output from this
.Nm
invocation.
.It Cm n$
Allows reordering of the output according to
.Ar argument .
@ -313,12 +316,48 @@ Consult the
manual page.
.Sh EXIT STATUS
.Ex -std
.Sh EXAMPLES
Print the string
.Qq hello :
.Bd -literal -offset indent
$ printf "%s\en" hello
hello
.Ed
.Pp
Same as above, but notice that the format string is not quoted and hence we
do not get the expected behavior:
.Bd -literal -offset indent
$ printf %s\en hello
hellon$
.Ed
.Pp
Print arguments forcing sign only for the first argument:
.Bd -literal -offset indent
$ printf "%+d\en%d\en%d\en" 1 -2 13
+1
-2
13
.Ed
.Pp
Same as above, but the single format string will be applied to the three
arguments:
.Bd -literal -offset indent
$ printf "%+d\en" 1 -2 13
+1
-2
+13
.Ed
.Pp
Print number using only two digits after the decimal point:
.Bd -literal -offset indent
$ printf "%.2f\en" 31.7456
31.75
.Ed
.Sh COMPATIBILITY
The traditional
.Bx
behavior of converting arguments of numeric formats not beginning
with a digit to the
.Tn ASCII
with a digit to the ASCII
code of the first character is not supported.
.Sh SEE ALSO
.Xr builtin 1 ,
@ -340,8 +379,7 @@ It is modeled
after the standard library function,
.Xr printf 3 .
.Sh CAVEATS
.Tn ANSI
hexadecimal character constants were deliberately not provided.
ANSI hexadecimal character constants were deliberately not provided.
.Pp
Trying to print a dash ("-") as the first character causes
.Nm
@ -361,10 +399,8 @@ and
formats with a precision
may not operate as expected.
.Sh BUGS
Since the floating point numbers are translated from
.Tn ASCII
to floating-point and
then back again, floating-point precision may be lost.
Since the floating point numbers are translated from ASCII
to floating-point and then back again, floating-point precision may be lost.
(By default, the number is translated to an IEEE-754 double-precision
value before being printed.
The

View File

@ -1,4 +1,7 @@
/*-
* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
* Copyright 2014 Garrett D'Amore <garrett@damore.org>
* Copyright 2010 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 1989, 1993
@ -12,7 +15,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
@ -46,7 +49,7 @@ static char const copyright[] =
static char const sccsid[] = "@(#)printf.c 8.1 (Berkeley) 7/20/93";
#endif
static const char rcsid[] =
"$FreeBSD: head/usr.bin/printf/printf.c 279503 2015-03-01 21:46:55Z jilles $";
"$FreeBSD$";
#endif /* not lint */
#include <sys/types.h>
@ -70,20 +73,15 @@ static const char rcsid[] =
#endif
#define PF(f, func) do { \
char *b = NULL; \
if (havewidth) \
if (haveprec) \
(void)asprintf(&b, f, fieldwidth, precision, func); \
(void)printf(f, fieldwidth, precision, func); \
else \
(void)asprintf(&b, f, fieldwidth, func); \
(void)printf(f, fieldwidth, func); \
else if (haveprec) \
(void)asprintf(&b, f, precision, func); \
(void)printf(f, precision, func); \
else \
(void)asprintf(&b, f, func); \
if (b) { \
(void)fputs(b, stdout); \
free(b); \
} \
(void)printf(f, func); \
} while (0)
static int asciicode(void);
@ -378,13 +376,25 @@ printf_doformat(char *fmt, int *rval)
char *p;
int getout;
p = strdup(getstr());
if (p == NULL) {
/* Convert "b" to "s" for output. */
start[strlen(start) - 1] = 's';
if ((p = strdup(getstr())) == NULL) {
warnx("%s", strerror(ENOMEM));
return (NULL);
}
getout = escape(p, 0, &len);
fputs(p, stdout);
/*
* Special-case conversion of zero; print it instead of
* feeding an empty string to printf("%s") which would not
* print anything.
*/
if (len == 1 && p[0] == '\0') {
putchar(p[0]);
} else {
PF(start, p);
}
/* Restore format for next loop. */
free(p);
if (getout)
return (end_fmt);
@ -394,7 +404,8 @@ printf_doformat(char *fmt, int *rval)
char p;
p = getchr();
PF(start, p);
if (p != '\0')
PF(start, p);
break;
}
case 's': {

View File

@ -2,15 +2,16 @@
<key>OpenSourceProject</key>
<string>printf</string>
<key>OpenSourceVersion</key>
<string>2015-03-01</string>
<string>2020-07-01</string>
<key>OpenSourceWebsiteURL</key>
<string>http://svnweb.freebsd.org/base/head/usr.bin/printf/</string>
<string>https://github.com/freebsd/freebsd/tree/master/usr.bin/printf</string>
<key>OpenSourceSCM</key>
<string>svn co http://svn.freebsd.org/base/head/usr.bin/printf/</string>
<string>https://github.com/freebsd/freebsd/tree/master/usr.bin/printf</string>
<key>OpenSourceImportDate</key>
<string>2015-07-23</string>
<string>2020-07-23</string>
<key>OpenSourceModifications</key>
<array>
<string>65959587: UNIX Conformance | /usr/bin/printf, multiple format assertion failures in VSC</string>
</array>
<key>OpenSourceLicense</key>
<string>bsd</string>

View File

@ -1,10 +1,11 @@
# $FreeBSD: head/usr.bin/printf/tests/Makefile 299094 2016-05-04 23:20:53Z ngie $
# $FreeBSD$
PACKAGE= tests
TAP_TESTS_SH= legacy_test
${PACKAGE}FILES+= regress.b.out
${PACKAGE}FILES+= regress.bwidth.out
${PACKAGE}FILES+= regress.d.out
${PACKAGE}FILES+= regress.f.out
${PACKAGE}FILES+= regress.l1.out

View File

@ -1,4 +1,4 @@
# $FreeBSD: head/usr.bin/printf/tests/Makefile.depend 296587 2016-03-09 22:46:01Z bdrewery $
# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \

View File

@ -1,5 +1,5 @@
#!/bin/sh
# $FreeBSD: head/usr.bin/printf/tests/legacy_test.sh 263227 2014-03-16 08:04:06Z jmmv $
# $FreeBSD$
SRCDIR="$(dirname "${0}")"; export SRCDIR

View File

@ -0,0 +1 @@
a

View File

@ -1,10 +1,8 @@
# $FreeBSD: head/usr.bin/printf/tests/regress.sh 266854 2014-05-29 19:48:18Z pfg $
enable -n printf
# $FreeBSD$
REGRESSION_START($1)
echo '1..23'
echo '1..24'
REGRESSION_TEST(`b', `printf "abc%b%b" "def\n" "\cghi"')
REGRESSION_TEST(`d', `printf "%d,%5d,%.5d,%0*d,%.*d\n" 123 123 123 5 123 5 123')
@ -29,5 +27,6 @@ REGRESSION_TEST(`missingpos1', `printf "%*.*1\$s" 1 1 1 2>&1')
REGRESSION_TEST(`missingpos1', `printf "%1\$*2\$.*s" 1 1 1 2>&1')
REGRESSION_TEST(`missingpos1', `printf "%*1\$.*2\$s" 1 1 1 2>&1')
REGRESSION_TEST(`missingpos1', `printf "%1\$*.*2\$s" 1 1 1 2>&1')
REGRESSION_TEST(`bwidth', `printf "%8.2b" "a\nb\n"')
REGRESSION_END()

View File

@ -1542,9 +1542,14 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
6C1C283E22FB822900E0AC67 /* su_entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = su_entitlements.plist; sourceTree = "<group>"; };
C6868576154725700025D623 /* systime */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = systime; sourceTree = BUILT_PRODUCTS_DIR; };
C6868579154725700025D623 /* systime.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = systime.c; sourceTree = "<group>"; };
C686857B154725700025D623 /* systime.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = systime.1; sourceTree = "<group>"; };
CE799E6024AD3B1B00E73238 /* test_time.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = test_time.sh; sourceTree = "<group>"; usesTabs = 1; };
CE799E6224B3982200E73238 /* install-files.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = "install-files.sh"; sourceTree = "<group>"; };
CE799E6324B3982200E73238 /* builtins.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = builtins.txt; sourceTree = "<group>"; };
CE799E6424B3982200E73238 /* builtins-manpages.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "builtins-manpages.txt"; sourceTree = "<group>"; };
FC5D636814B9808E00123E48 /* conv.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = conv.c; sourceTree = "<group>"; };
FC5D636914B9808E00123E48 /* display.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = display.c; sourceTree = "<group>"; };
FC5D636A14B9808E00123E48 /* hexdump.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = hexdump.1; sourceTree = "<group>"; };
@ -1660,7 +1665,7 @@
FCBA13FA14A141A300AA698B /* test.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = test.1; sourceTree = "<group>"; };
FCBA13FB14A141A300AA698B /* test.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = test.c; sourceTree = "<group>"; };
FCBA13FF14A141A300AA698B /* time.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = time.1; sourceTree = "<group>"; };
FCBA140014A141A300AA698B /* time.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = time.c; sourceTree = "<group>"; };
FCBA140014A141A300AA698B /* time.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = time.c; sourceTree = "<group>"; usesTabs = 1; };
FCBA140314A141A300AA698B /* true.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = true.1; sourceTree = "<group>"; };
FCBA140414A141A300AA698B /* true.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = true.c; sourceTree = "<group>"; };
FCBA140814A141A300AA698B /* uname.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = uname.1; sourceTree = "<group>"; };
@ -2193,6 +2198,24 @@
path = systime;
sourceTree = "<group>";
};
CE799E5F24AD3B1B00E73238 /* tests */ = {
isa = PBXGroup;
children = (
CE799E6024AD3B1B00E73238 /* test_time.sh */,
);
path = tests;
sourceTree = "<group>";
};
CE799E6124B3982200E73238 /* xcodescripts */ = {
isa = PBXGroup;
children = (
CE799E6224B3982200E73238 /* install-files.sh */,
CE799E6324B3982200E73238 /* builtins.txt */,
CE799E6424B3982200E73238 /* builtins-manpages.txt */,
);
path = xcodescripts;
sourceTree = "<group>";
};
FC5D636714B9808E00123E48 /* hexdump */ = {
isa = PBXGroup;
children = (
@ -2221,6 +2244,7 @@
FC80BF5514A05A2F00C6F7F5 = {
isa = PBXGroup;
children = (
CE799E6124B3982200E73238 /* xcodescripts */,
FD60612F1B7D2DDE004BCA6A /* xcconfigs */,
FCBA134014A141A300AA698B /* alias */,
FCBA134514A141A300AA698B /* apply */,
@ -2679,6 +2703,7 @@
FCBA13EE14A141A300AA698B /* su */ = {
isa = PBXGroup;
children = (
6C1C283E22FB822900E0AC67 /* su_entitlements.plist */,
FCBA13F014A141A300AA698B /* su.1 */,
FCBA13F114A141A300AA698B /* su.c */,
FCBA13F214A141A300AA698B /* su.pam */,
@ -2710,6 +2735,7 @@
FCBA13FD14A141A300AA698B /* time */ = {
isa = PBXGroup;
children = (
CE799E5F24AD3B1B00E73238 /* tests */,
FCBA13FF14A141A300AA698B /* time.1 */,
FCBA140014A141A300AA698B /* time.c */,
);
@ -3904,7 +3930,7 @@
);
runOnlyForDeploymentPostprocessing = 1;
shellPath = /bin/sh;
shellScript = ". \"$PROJECT_DIR\"/xcodescripts/install-files.sh";
shellScript = ". \"$PROJECT_DIR\"/xcodescripts/install-files.sh\n";
showEnvVarsInLog = 0;
};
FCE30F4D14B619C900CC0294 /* Run Script */ = {
@ -3919,7 +3945,7 @@
);
runOnlyForDeploymentPostprocessing = 1;
shellPath = /bin/sh;
shellScript = ". \"$PROJECT_DIR\"/xcodescripts/install-files.sh";
shellScript = ". \"$PROJECT_DIR\"/xcodescripts/install-files.sh\n";
showEnvVarsInLog = 0;
};
FD6060EF1B7C0590004BCA6A /* mkbuiltins */ = {
@ -3957,7 +3983,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "env -i xcrun -sdk macosx cc ${SRCROOT}/sh/mknodes.c -o ${DERIVED_FILE_DIR}/mknodes\ncd ${BUILT_PRODUCTS_DIR} && ${DERIVED_FILE_DIR}/mknodes ${SRCROOT}/sh/nodetypes ${SRCROOT}/sh/nodes.c.pat";
shellScript = "mkdir -p ${DERIVED_FILE_DIR}\nenv -i xcrun -sdk macosx cc ${SRCROOT}/sh/mknodes.c -o ${DERIVED_FILE_DIR}/mknodes\ncd ${BUILT_PRODUCTS_DIR} && ${DERIVED_FILE_DIR}/mknodes ${SRCROOT}/sh/nodetypes ${SRCROOT}/sh/nodes.c.pat\n";
};
FD6060F21B7C0744004BCA6A /* mksyntax */ = {
isa = PBXShellScriptBuildPhase;
@ -5296,6 +5322,7 @@
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_OBJC_WEAK = YES;
CODE_SIGN_ENTITLEMENTS = su/su_entitlements.plist;
INSTALL_MODE_FLAG = "u+s,u+w,go-w,a+rX";
PRODUCT_NAME = "$(TARGET_NAME)";
};

10
su/su_entitlements.plist Normal file
View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.keystore.console</key>
<true/>
<key>com.apple.private.security.clear-library-validation</key>
<true/>
</dict>
</plist>

View File

@ -12,10 +12,8 @@
<string>/bin/sh</string>
<string>/AppleInternal/Tests/shell_cmds/printf/legacy_test.sh</string>
</array>
<key>IgnoreOutput</key>
<true/>
<key>TestName</key>
<string>shell_cmds: printf</string>
<key>IgnoreOutput</key><true/>
<key>TestName</key><string>shell_cmds.printf</string>
<key>WhenToRun</key>
<array>
<string>PRESUBMISSION</string>
@ -28,8 +26,20 @@
<string>/bin/sh</string>
<string>/AppleInternal/Tests/shell_cmds/test/legacy_test.sh</string>
</array>
<key>TestName</key>
<string>shell_cmds: test</string>
<key>TestName</key><string>shell_cmds.test</string>
<key>WhenToRun</key>
<array>
<string>PRESUBMISSION</string>
<string>NIGHTLY</string>
</array>
</dict>
<dict>
<key>Command</key>
<array>
<string>/bin/sh</string>
<string>/AppleInternal/Tests/shell_cmds/time/test_time.sh</string>
</array>
<key>TestName</key><string>shell_cmds.time</string>
<key>WhenToRun</key>
<array>
<string>PRESUBMISSION</string>

60
time/tests/test_time.sh Executable file
View File

@ -0,0 +1,60 @@
#!/bin/sh
set -o nounset
TIME="${TIME-/usr/bin/time}"
echo "SUITE: time(1)"
what $TIME
echo
EXIT=0
echo TEST: check real time
TIME_SLEEP=`$TIME 2>&1 sleep 1 | sed -n -E 's/[ ]+([0-9]+).*/\1/p'`
TIME_STATUS=$?
if [ "$TIME_STATUS" -ne "0" ]; then
echo FAIL: time failed with "$TIME_STATUS"
EXIT=1
fi
if [ "$TIME_SLEEP" -lt "0" ]; then
echo FAIL: time mis-timed sleep
EXIT=2
fi
MONOTONIC=`sysctl -n kern.monotonic.task_thread_counting`
if [ "$MONOTONIC" -ne "0" ]; then
echo TEST: check instructions retired
TIME_INSTRS=`$TIME -l 2>&1 sleep 1 | sed -E -n '/instructions/p'`
if [ -z "$TIME_INSTRS" ]; then
echo FAIL: time is not showing instructions retired
EXIT=3
fi
else
echo SKIP: check instructions retired
fi
# NB: SIGINT and SIGQUIT work locally, but the automated test harnesses tries to
# handle those signals itself before the fork.
echo TEST: check child SIGUSR1
TIME_USR1=`$TIME 2>&1 sh -c 'kill -USR1 $$ && sleep 5 && true'`
TIME_STATUS=$?
if [ "$TIME_STATUS" -eq "0" ]; then
echo FAIL: time should allow child to receive SIGUSR1
EXIT=4
fi
echo TEST: check non-existent binary
TIME_NONEXIST=`$TIME 2>&1 ./this-wont-exist`
TIME_STATUS=$?
if [ "$TIME_STATUS" -ne "127" ]; then
echo FAIL: time should error when measuring a non-existent command
EXIT=5
fi
exit $EXIT

View File

@ -114,7 +114,3 @@ The
.Nm
utility conforms to
.St -p1003.2-92 .
.Sh BUGS
The granularity of seconds on microprocessors is crude and
can result in times being reported for CPU usage which are too large by
a second.

View File

@ -33,52 +33,48 @@
* SUCH DAMAGE.
*/
#include <errno.h>
#include <err.h>
#include <inttypes.h>
#include <langinfo.h>
#include <libproc.h>
#include <locale.h>
#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT("@(#) Copyright (c) 1987, 1988, 1993\n\
The Regents of the University of California. All rights reserved.\n");
#endif /* not lint */
#ifndef lint
#if 0
static char sccsid[] = "@(#)time.c 8.1 (Berkeley) 6/6/93";
#endif
__RCSID("$NetBSD: time.c,v 1.9 1997/10/20 03:28:21 lukem Exp $");
#endif /* not lint */
#include <sysexits.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/wait.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <errno.h>
#include <langinfo.h>
#include <locale.h>
int lflag;
int portableflag;
bool child_running = true;
int main __P((int, char **));
void
child_handler(int sig)
{
child_running = false;
}
int
main(argc, argv)
int argc;
char **argv;
main(int argc, char **argv)
{
int pid;
int ch, status;
struct timeval before, after;
int ch, status, rusage_ret = -1;
uint64_t before_ns, after_ns, duration_ns, duration_secs, duration_frac_ns;
struct rusage ru;
char * radix = NULL;
struct rusage_info_v4 ruinfo;
sigset_t sigmask, suspmask, origmask;
#ifdef __GNUC__ /* XXX: borken gcc */
(void)&argv;
#endif
lflag = 0;
while ((ch = getopt(argc, argv, "lp")) != -1)
while ((ch = getopt(argc, argv, "lp")) != -1) {
switch((char)ch) {
case 'p':
portableflag = 1;
@ -88,37 +84,88 @@ main(argc, argv)
break;
case '?':
default:
fprintf(stderr, "usage: time [-lp] command.\n");
fprintf(stderr, "usage: time [-lp] <command>\n");
exit(1);
}
}
if (!(argc -= optind))
if (!(argc -= optind)) {
exit(0);
}
argv += optind;
gettimeofday(&before, (struct timezone *)NULL);
switch(pid = vfork()) {
case -1: /* error */
perror("time");
exit(1);
/* NOTREACHED */
case 0: /* child */
sigemptyset(&sigmask);
/*
* Block SIGCHLD so that the check for `child_running` doesn't miss the
* handler before calling `sigsuspend` and blocking forever.
*/
sigaddset(&sigmask, SIGCHLD);
sigprocmask(SIG_BLOCK, &sigmask, &origmask);
/*
* Ensure child signals are handled by the parent prior to fork; otherwise,
* they could be missed between the child forking and calling `sigsuspend`.
*/
(void)signal(SIGCHLD, child_handler);
sigemptyset(&suspmask);
before_ns = clock_gettime_nsec_np(CLOCK_UPTIME_RAW);
/*
* NB: Don't add anything between these two lines -- measurement is
* happening now.
*/
switch (pid = vfork()) {
case -1: /* error */
err(EX_OSERR, "time");
__builtin_unreachable();
case 0: /* child */
/*
* Allow the child to respond to signals by resetting to the original
* signal handling behavior.
*/
(void)sigprocmask(SIG_SETMASK, &origmask, NULL);
execvp(*argv, argv);
perror(*argv);
_exit((errno == ENOENT) ? 127 : 126);
/* NOTREACHED */
__builtin_unreachable();
default: /* parent */
break;
}
/* parent */
/*
* Let the child handle signals that normally exit.
*/
(void)signal(SIGINT, SIG_IGN);
(void)signal(SIGQUIT, SIG_IGN);
while (wait3(&status, 0, &ru) != pid);
gettimeofday(&after, (struct timezone *)NULL);
if (!WIFEXITED(status))
while (child_running) {
/*
* This would be racy, but SIGCHLD is blocked above (as part of
* `sigmask`.
*/
sigsuspend(&suspmask);
}
/*
* NB: Minimize what's added between these statements to preserve the
* accuracy of the time measurement.
*/
after_ns = clock_gettime_nsec_np(CLOCK_UPTIME_RAW);
if (lflag) {
rusage_ret = proc_pid_rusage(pid, RUSAGE_INFO_V4, (void **)&ruinfo);
}
while (wait3(&status, 0, &ru) != pid) {
}
if (!WIFEXITED(status)) {
fprintf(stderr, "Command terminated abnormally.\n");
timersub(&after, &before, &after);
}
duration_ns = after_ns - before_ns;
duration_secs = duration_ns / (1000 * 1000 * 1000);
duration_frac_ns = duration_ns - (duration_secs * 1000 * 1000 * 1000);
if (portableflag) {
char *radix = NULL;
setlocale(LC_ALL, "");
radix = nl_langinfo(RADIXCHAR);
@ -126,15 +173,15 @@ main(argc, argv)
radix = ".";
}
fprintf (stderr, "real %9ld%s%02ld\n",
(long)after.tv_sec, radix, (long)after.tv_usec/10000);
fprintf (stderr, "user %9ld%s%02ld\n",
fprintf(stderr, "real %9" PRIu64 "%s%02" PRIu64 "\n",
duration_secs, radix, duration_frac_ns / (10 * 1000 * 1000));
fprintf(stderr, "user %9ld%s%02ld\n",
(long)ru.ru_utime.tv_sec, radix, (long)ru.ru_utime.tv_usec/10000);
fprintf (stderr, "sys %9ld%s%02ld\n",
fprintf(stderr, "sys %9ld%s%02ld\n",
(long)ru.ru_stime.tv_sec, radix, (long)ru.ru_stime.tv_usec/10000);
} else {
fprintf(stderr, "%9ld.%02ld real ",
(long)after.tv_sec, (long)after.tv_usec/10000);
fprintf(stderr, "%9" PRIu64 ".%02" PRIu64 " real ",
duration_secs, duration_frac_ns / (10 * 1000 * 1000));
fprintf(stderr, "%9ld.%02ld user ",
(long)ru.ru_utime.tv_sec, (long)ru.ru_utime.tv_usec/10000);
fprintf(stderr, "%9ld.%02ld sys\n",
@ -142,41 +189,57 @@ main(argc, argv)
}
if (lflag) {
int hz = 100; /* XXX */
int hz = 100; /* XXX */
long ticks;
ticks = hz * (ru.ru_utime.tv_sec + ru.ru_stime.tv_sec) +
hz * (ru.ru_utime.tv_usec + ru.ru_stime.tv_usec) / 1000000;
fprintf(stderr, "%10ld %s\n",
fprintf(stderr, "%20ld %s\n",
ru.ru_maxrss, "maximum resident set size");
fprintf(stderr, "%10ld %s\n", ticks ? ru.ru_ixrss / ticks : 0,
fprintf(stderr, "%20ld %s\n", ticks ? ru.ru_ixrss / ticks : 0,
"average shared memory size");
fprintf(stderr, "%10ld %s\n", ticks ? ru.ru_idrss / ticks : 0,
fprintf(stderr, "%20ld %s\n", ticks ? ru.ru_idrss / ticks : 0,
"average unshared data size");
fprintf(stderr, "%10ld %s\n", ticks ? ru.ru_isrss / ticks : 0,
fprintf(stderr, "%20ld %s\n", ticks ? ru.ru_isrss / ticks : 0,
"average unshared stack size");
fprintf(stderr, "%10ld %s\n",
fprintf(stderr, "%20ld %s\n",
ru.ru_minflt, "page reclaims");
fprintf(stderr, "%10ld %s\n",
fprintf(stderr, "%20ld %s\n",
ru.ru_majflt, "page faults");
fprintf(stderr, "%10ld %s\n",
fprintf(stderr, "%20ld %s\n",
ru.ru_nswap, "swaps");
fprintf(stderr, "%10ld %s\n",
fprintf(stderr, "%20ld %s\n",
ru.ru_inblock, "block input operations");
fprintf(stderr, "%10ld %s\n",
fprintf(stderr, "%20ld %s\n",
ru.ru_oublock, "block output operations");
fprintf(stderr, "%10ld %s\n",
fprintf(stderr, "%20ld %s\n",
ru.ru_msgsnd, "messages sent");
fprintf(stderr, "%10ld %s\n",
fprintf(stderr, "%20ld %s\n",
ru.ru_msgrcv, "messages received");
fprintf(stderr, "%10ld %s\n",
fprintf(stderr, "%20ld %s\n",
ru.ru_nsignals, "signals received");
fprintf(stderr, "%10ld %s\n",
fprintf(stderr, "%20ld %s\n",
ru.ru_nvcsw, "voluntary context switches");
fprintf(stderr, "%10ld %s\n",
fprintf(stderr, "%20ld %s\n",
ru.ru_nivcsw, "involuntary context switches");
if (rusage_ret >= 0) {
if (ruinfo.ri_instructions > 0) {
fprintf(stderr, "%20" PRIu64 " %s\n", ruinfo.ri_instructions,
"instructions retired");
}
if (ruinfo.ri_cycles > 0) {
fprintf(stderr, "%20" PRIu64 " %s\n", ruinfo.ri_cycles,
"cycles elapsed");
}
if (ruinfo.ri_lifetime_max_phys_footprint > 0) {
fprintf(stderr, "%20" PRIu64 " %s\n",
ruinfo.ri_lifetime_max_phys_footprint,
"peak memory footprint");
}
}
}
exit (WIFEXITED(status) ? WEXITSTATUS(status) : EXIT_FAILURE);
exit(WIFEXITED(status) ? WEXITSTATUS(status) : EXIT_FAILURE);
}

View File

@ -1,4 +1,6 @@
/*-
* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
@ -10,11 +12,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
@ -30,6 +28,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*
* @(#)pathnames.h 8.1 (Berkeley) 6/6/93
*/

View File

@ -36,7 +36,19 @@ strnsubst(char **str, const char *match, const char *replstr, size_t maxsize)
s1 = *str;
if (s1 == NULL)
return;
s2 = calloc(maxsize, 1);
/*
* If maxsize is 0 then set it to the length of s1, because we have
* to duplicate s1. XXX we maybe should double-check whether the match
* appears in s1. If it doesn't, then we also have to set the length
* to the length of s1, to avoid modifying the argument. It may make
* sense to check if maxsize is <= strlen(s1), because in that case we
* want to return the unmodified string, too.
*/
if (maxsize == 0) {
match = NULL;
maxsize = strlen(s1) + 1;
}
s2 = calloc(1, maxsize);
if (s2 == NULL)
err(1, "calloc");

View File

@ -13,11 +13,7 @@
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by the University of
.\" California, Berkeley and its contributors.
.\" 4. Neither the name of the University nor the names of its contributors
.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
@ -37,7 +33,7 @@
.\" $FreeBSD: src/usr.bin/xargs/xargs.1,v 1.34 2005/05/21 09:55:09 ru Exp $
.\" $xMach: xargs.1,v 1.2 2002/02/23 05:23:37 tim Exp $
.\"
.Dd August 2, 2004
.Dd August 4, 2015
.Dt XARGS 1
.Os
.Sh NAME
@ -45,11 +41,12 @@
.Nd "construct argument list(s) and execute utility"
.Sh SYNOPSIS
.Nm
.Op Fl 0opt
.Op Fl 0oprt
.Op Fl E Ar eofstr
.Oo
.Fl I Ar replstr
.Op Fl R Ar replacements
.Op Fl S Ar replsize
.Oc
.Op Fl J Ar replstr
.Op Fl L Ar number
@ -74,8 +71,7 @@ Any arguments specified on the command line are given to
upon each invocation, followed by some number of the arguments read
from the standard input of
.Nm .
The utility
is repeatedly executed until standard input is exhausted.
This is repeated until standard input is exhausted.
.Pp
Spaces, tabs and newlines may be embedded in arguments using single
(``\ '\ '')
@ -115,13 +111,20 @@ flag is specified) arguments to
.Ar utility
with the entire line of input.
The resulting arguments, after replacement is done, will not be allowed to grow
beyond 255 bytes; this is implemented by concatenating as much of the argument
beyond
.Ar replsize
(or 255 if no
.Fl S
flag is specified)
bytes; this is implemented by concatenating as much of the argument
containing
.Ar replstr
as possible, to the constructed arguments to
.Ar utility ,
up to 255 bytes.
The 255 byte limit does not apply to arguments to
up to
.Ar replsize
bytes.
The size limit does not apply to arguments to
.Ar utility
which do not contain
.Ar replstr ,
@ -160,8 +163,7 @@ directories which start with an uppercase letter in the current
directory to
.Pa destdir :
.Pp
.Dl /bin/ls -1d [A-Z]* | xargs -J % cp -rp % destdir
.Pp
.Dl /bin/ls -1d [A-Z]* | xargs -J % cp -Rp % destdir
.It Fl L Ar number
Call
.Ar utility
@ -211,6 +213,11 @@ Parallel mode: run at most
invocations of
.Ar utility
at once.
If
.Ar maxprocs
is set to 0,
.Nm
will run as many processes as possible.
.It Fl p
Echo each command to be executed and ask the user whether it should be
executed.
@ -220,6 +227,34 @@ in the POSIX locale,
causes the command to be executed, any other response causes it to be
skipped.
No commands are executed if the process is not attached to a terminal.
.It Fl r
Compatibility with GNU
.Nm .
The GNU version of
.Nm
runs the
.Ar utility
argument at least once, even if
.Nm
input is empty, and it supports a
.Fl r
option to inhibit this behavior.
The
.Fx
version of
.Nm
does not run the
.Ar utility
argument on empty input, but it supports the
.Fl r
option for command-line compatibility with GNU
.Nm ,
but the
.Fl r
option does nothing in the
.Fx
version of
.Nm .
.It Fl R Ar replacements
Specify the maximum number of arguments that
.Fl I
@ -227,6 +262,13 @@ will do replacement in.
If
.Ar replacements
is negative, the number of arguments in which to replace is unbounded.
.It Fl S Ar replsize
Specify the amount of space (in bytes) that
.Fl I
can use for replacements.
The default for
.Ar replsize
is 255.
.It Fl s Ar size
Set the maximum number of bytes for the command line length provided to
.Ar utility .
@ -272,7 +314,11 @@ cannot be invoked, an invocation of
is terminated by a signal,
or an invocation of
.Ar utility
exits with a value of 255.
exits with a value of 255, the
.Nm
utility stops processing input and exits after all invocations of
.Ar utility
finish processing.
.Sh LEGACY DESCRIPTION
In legacy mode, the
.Fl L
@ -314,16 +360,16 @@ utility is expected to be
.St -p1003.2
compliant.
The
.Fl J , o , P
.Fl J , o , P, R
and
.Fl R
.Fl S
options are non-standard
.Fx
extensions which may not be available on other operating systems.
.Sh HISTORY
The
.Nm
command appeared in PWB UNIX.
utility appeared in PWB UNIX.
.Sh BUGS
If
.Ar utility

View File

@ -1,4 +1,6 @@
/*-
* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
@ -13,11 +15,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
@ -48,11 +46,13 @@ static char sccsid[] = "@(#)xargs.c 8.1 (Berkeley) 6/6/93";
#endif /* not lint */
#endif
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/usr.bin/xargs/xargs.c,v 1.57 2005/02/27 02:01:31 gad Exp $");
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/param.h>
#include <sys/resource.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
@ -79,7 +79,17 @@ static int prompt(void);
static void run(char **);
static void usage(void);
void strnsubst(char **, const char *, const char *, size_t);
static pid_t xwait(int block, int *status);
static void xexit(const char *, const int);
static void waitchildren(const char *, int);
static void pids_init(void);
static int pids_empty(void);
static int pids_full(void);
static void pids_add(pid_t pid);
static int pids_remove(pid_t pid);
static int findslot(pid_t pid);
static int findfreeslot(void);
static void clearslot(int slot);
static int last_was_newline = 1;
static int last_was_blank = 0;
@ -89,9 +99,10 @@ static char **av, **bxp, **ep, **endxp, **xp;
static char *argp, *bbp, *ebp, *inpline, *p, *replstr;
static const char *eofstr;
static int count, insingle, indouble, oflag, pflag, tflag, Rflag, rval, zflag;
static int cnt, Iflag, jfound, Lflag, wasquoted, xflag;
static int cnt, Iflag, jfound, Lflag, Sflag, wasquoted, xflag;
static int curprocs, maxprocs;
static size_t pad9314053;
static pid_t *childpids;
static volatile int childerr;
@ -104,7 +115,9 @@ main(int argc, char *argv[])
int ch, Jflag, nflag, nline;
size_t nargs;
size_t linelen;
struct rlimit rl;
char *endptr;
const char *errstr;
inpline = replstr = NULL;
ep = environ;
@ -137,8 +150,8 @@ main(int argc, char *argv[])
}
nline -= pad9314053;
maxprocs = 1;
while ((ch = getopt(argc, argv, "0E:I:J:L:n:oP:pR:s:tx")) != -1)
switch(ch) {
while ((ch = getopt(argc, argv, "0E:I:J:L:n:oP:pR:S:s:rtx")) != -1)
switch (ch) {
case 'E':
eofstr = optarg;
break;
@ -154,7 +167,9 @@ main(int argc, char *argv[])
replstr = optarg;
break;
case 'L':
Lflag = atoi(optarg);
Lflag = strtonum(optarg, 0, INT_MAX, &errstr);
if (errstr)
errx(1, "-L %s: %s", optarg, errstr);
if (COMPAT_MODE("bin/xargs", "Unix2003")) {
nflag = 0; /* Override */
nargs = 5000;
@ -172,8 +187,13 @@ main(int argc, char *argv[])
oflag = 1;
break;
case 'P':
if ((maxprocs = atoi(optarg)) <= 0)
errx(1, "max. processes must be >0");
maxprocs = strtonum(optarg, 0, INT_MAX, &errstr);
if (errstr)
errx(1, "-P %s: %s", optarg, errstr);
if (getrlimit(RLIMIT_NPROC, &rl) != 0)
errx(1, "getrlimit failed");
if (maxprocs == 0 || maxprocs > rl.rlim_cur)
maxprocs = rl.rlim_cur;
break;
case 'p':
pflag = 1;
@ -183,8 +203,18 @@ main(int argc, char *argv[])
if (*endptr != '\0')
errx(1, "replacements must be a number");
break;
case 'r':
/* GNU compatibility */
break;
case 'S':
Sflag = strtoul(optarg, &endptr, 10);
if (*endptr != '\0')
errx(1, "replsize must be a number");
break;
case 's':
nline = atoi(optarg);
nline = strtonum(optarg, 0, INT_MAX, &errstr);
if (errstr)
errx(1, "-s %s: %s", optarg, errstr);
pad9314053 = 0; /* assume the -s value is valid */
break;
case 't':
@ -205,8 +235,12 @@ main(int argc, char *argv[])
if (!Iflag && Rflag)
usage();
if (!Iflag && Sflag)
usage();
if (Iflag && !Rflag)
Rflag = 5;
if (Iflag && !Sflag)
Sflag = 255;
if (xflag && !nflag)
usage();
if (Iflag || Lflag)
@ -214,13 +248,15 @@ main(int argc, char *argv[])
if (replstr != NULL && *replstr == '\0')
errx(1, "replstr may not be empty");
pids_init();
/*
* Allocate pointers for the utility name, the utility arguments,
* the maximum arguments to be read from stdin and the trailing
* NULL.
*/
linelen = 1 + argc + nargs + 1;
if ((av = bxp = malloc(linelen * sizeof(char **))) == NULL)
if ((av = bxp = malloc(linelen * sizeof(char *))) == NULL)
errx(1, "malloc failed");
/*
@ -279,13 +315,11 @@ parse_input(int argc, char *argv[])
foundeof = 0;
switch(ch = getchar()) {
switch (ch = getchar()) {
case EOF:
/* No arguments since last exec. */
if (p == bbp) {
waitchildren(*argv, 1);
exit(rval);
}
if (p == bbp)
xexit(*av, rval);
goto arg1;
case ' ':
last_was_blank = 1;
@ -323,11 +357,13 @@ parse_input(int argc, char *argv[])
last_was_newline = 1;
/* Quotes do not escape newlines. */
arg1: if (insingle || indouble)
errx(1, "unterminated quote");
arg1: if (insingle || indouble) {
warnx("unterminated quote");
xexit(*av, 1);
}
arg2:
foundeof = *eofstr != '\0' &&
strcmp(argp, eofstr) == 0;
strncmp(argp, eofstr, p - argp) == 0;
#ifdef __APPLE__
/* 6591323: -I specifies that it processes the entire line,
@ -370,8 +406,10 @@ arg2:
*/
inpline = realloc(inpline, curlen + 2 +
strlen(argp));
if (inpline == NULL)
errx(1, "realloc failed");
if (inpline == NULL) {
warnx("realloc failed");
xexit(*av, 1);
}
if (curlen == 1)
strcpy(inpline, argp);
else
@ -388,17 +426,17 @@ arg2:
*/
if (xp == endxp || p + (count * pad9314053) > ebp || ch == EOF ||
(Lflag <= count && xflag) || foundeof) {
if (xflag && xp != endxp && p + (count * pad9314053) > ebp)
errx(1, "insufficient space for arguments");
if (xflag && xp != endxp && p + (count * pad9314053) > ebp) {
warnx("insufficient space for arguments");
xexit(*av, 1);
}
if (jfound) {
for (avj = argv; *avj; avj++)
*xp++ = *avj;
}
prerun(argc, av);
if (ch == EOF || foundeof) {
waitchildren(*argv, 1);
exit(rval);
}
if (ch == EOF || foundeof)
xexit(*av, rval);
p = bbp;
xp = bxp;
count = 0;
@ -423,8 +461,10 @@ arg2:
if (zflag)
goto addch;
/* Backslash escapes anything, is escaped by quotes. */
if (!insingle && !indouble && (ch = getchar()) == EOF)
errx(1, "backslash at EOF");
if (!insingle && !indouble && (ch = getchar()) == EOF) {
warnx("backslash at EOF");
xexit(*av, 1);
}
/* FALLTHROUGH */
default:
addch: if (p < ebp) {
@ -433,11 +473,15 @@ addch: if (p < ebp) {
}
/* If only one argument, not enough buffer space. */
if (bxp == xp)
errx(1, "insufficient space for argument");
if (bxp == xp) {
warnx("insufficient space for argument");
xexit(*av, 1);
}
/* Didn't hit argument limit, so if xflag object. */
if (xflag)
errx(1, "insufficient space for arguments");
if (xflag) {
warnx("insufficient space for arguments");
xexit(*av, 1);
}
if (jfound) {
for (avj = argv; *avj; avj++)
@ -481,17 +525,21 @@ prerun(int argc, char *argv[])
* Allocate memory to hold the argument list, and
* a NULL at the tail.
*/
tmp = malloc((argc + 1) * sizeof(char**));
if (tmp == NULL)
errx(1, "malloc failed");
tmp = malloc((argc + 1) * sizeof(char *));
if (tmp == NULL) {
warnx("malloc failed");
xexit(*argv, 1);
}
tmp2 = tmp;
/*
* Save the first argument and iterate over it, we
* cannot do strnsubst() to it.
*/
if ((*tmp++ = strdup(*avj++)) == NULL)
errx(1, "strdup failed");
if ((*tmp++ = strdup(*avj++)) == NULL) {
warnx("strdup failed");
xexit(*argv, 1);
}
/*
* For each argument to utility, if we have not used up
@ -504,12 +552,14 @@ prerun(int argc, char *argv[])
while (--argc) {
*tmp = *avj++;
if (repls && strstr(*tmp, replstr) != NULL) {
strnsubst(tmp++, replstr, inpline, (size_t)255);
strnsubst(tmp++, replstr, inpline, (size_t)Sflag);
if (repls > 0)
repls--;
} else {
if ((*tmp = strdup(*tmp)) == NULL)
errx(1, "strdup failed");
if ((*tmp = strdup(*tmp)) == NULL) {
warnx("strdup failed");
xexit(*argv, 1);
}
tmp++;
}
}
@ -578,9 +628,10 @@ run(char **argv)
}
exec:
childerr = 0;
switch(pid = vfork()) {
switch (pid = vfork()) {
case -1:
err(1, "vfork");
warn("vfork");
xexit(*argv, 1);
case 0:
if (oflag) {
if ((fd = open(_PATH_TTY, O_RDONLY)) == -1)
@ -597,35 +648,156 @@ exec:
childerr = errno;
_exit(1);
}
curprocs++;
pids_add(pid);
waitchildren(*argv, 0);
}
/*
* Wait for a tracked child to exit and return its pid and exit status.
*
* Ignores (discards) all untracked child processes.
* Returns -1 and sets errno to ECHILD if no tracked children exist.
* If block is set, waits indefinitely for a child process to exit.
* If block is not set and no children have exited, returns 0 immediately.
*/
static pid_t
xwait(int block, int *status) {
pid_t pid;
if (pids_empty()) {
errno = ECHILD;
return (-1);
}
while ((pid = waitpid(-1, status, block ? 0 : WNOHANG)) > 0)
if (pids_remove(pid))
break;
return (pid);
}
static void
xexit(const char *name, const int exit_code) {
waitchildren(name, 1);
exit(exit_code);
}
static void
waitchildren(const char *name, int waitall)
{
pid_t pid;
int status;
int cause_exit = 0;
while ((pid = waitpid(-1, &status, !waitall && curprocs < maxprocs ?
WNOHANG : 0)) > 0) {
curprocs--;
/* If we couldn't invoke the utility, exit. */
if (childerr != 0) {
errno = childerr;
err(errno == ENOENT ? 127 : 126, "%s", name);
}
while ((pid = xwait(waitall || pids_full(), &status)) > 0) {
/*
* If utility signaled or exited with a value of 255,
* exit 1-125.
* If we couldn't invoke the utility or if utility exited
* because of a signal or with a value of 255, warn (per
* POSIX), and then wait until all other children have
* exited before exiting 1-125. POSIX requires us to stop
* reading if child exits because of a signal or with 255,
* but it does not require us to exit immediately; waiting
* is preferable to orphaning.
*/
if (WIFSIGNALED(status) || WEXITSTATUS(status) == 255)
exit(1);
if (WEXITSTATUS(status))
rval = 1;
if (childerr != 0 && cause_exit == 0) {
errno = childerr;
waitall = 1;
cause_exit = errno == ENOENT ? 127 : 126;
warn("%s", name);
} else if (WIFSIGNALED(status)) {
waitall = cause_exit = 1;
warnx("%s: terminated with signal %d; aborting",
name, WTERMSIG(status));
} else if (WEXITSTATUS(status) == 255) {
waitall = cause_exit = 1;
warnx("%s: exited with status 255; aborting", name);
} else if (WEXITSTATUS(status))
rval = 1;
}
if (cause_exit)
exit(cause_exit);
if (pid == -1 && errno != ECHILD)
err(1, "wait3");
err(1, "waitpid");
}
#define NOPID (0)
static void
pids_init(void)
{
int i;
if ((childpids = malloc(maxprocs * sizeof(*childpids))) == NULL)
errx(1, "malloc failed");
for (i = 0; i < maxprocs; i++)
clearslot(i);
}
static int
pids_empty(void)
{
return (curprocs == 0);
}
static int
pids_full(void)
{
return (curprocs >= maxprocs);
}
static void
pids_add(pid_t pid)
{
int slot;
slot = findfreeslot();
childpids[slot] = pid;
curprocs++;
}
static int
pids_remove(pid_t pid)
{
int slot;
if ((slot = findslot(pid)) < 0)
return (0);
clearslot(slot);
curprocs--;
return (1);
}
static int
findfreeslot(void)
{
int slot;
if ((slot = findslot(NOPID)) < 0)
errx(1, "internal error: no free pid slot");
return (slot);
}
static int
findslot(pid_t pid)
{
int slot;
for (slot = 0; slot < maxprocs; slot++)
if (childpids[slot] == pid)
return (slot);
return (-1);
}
static void
clearslot(int slot)
{
childpids[slot] = NOPID;
}
/*
@ -649,6 +821,7 @@ prompt(void)
(void)fclose(ttyfp);
return (0);
}
response[rsize - 1] = '\0';
match = regexec(&cre, response, 0, NULL, 0);
(void)fclose(ttyfp);
regfree(&cre);
@ -658,9 +831,10 @@ prompt(void)
static void
usage(void)
{
fprintf(stderr,
"usage: xargs [-0opt] [-E eofstr] [-I replstr [-R replacements]] [-J replstr]\n"
" [-L number] [-n number [-x]] [-P maxprocs] [-s size]\n"
" [utility [argument ...]]\n");
"usage: xargs [-0opt] [-E eofstr] [-I replstr [-R replacements] [-S replsize]]\n"
" [-J replstr] [-L number] [-n number [-x]] [-P maxprocs]\n"
" [-s size] [utility [argument ...]]\n");
exit(1);
}

View File

@ -31,6 +31,20 @@ for manpage in `cat "$SRCROOT/xcodescripts/builtins-manpages.txt"`; do
done
set -x
install -d -o root -g wheel -m 0755 "$DSTROOT"/AppleInternal/Tests/shell_cmds
install -o root -g wheel -m 0644 "$SRCROOT"/tests/regress.m4 \
"$DSTROOT"/AppleInternal/Tests/shell_cmds
install -d -o root -g wheel -m 0755 \
"$DSTROOT"/AppleInternal/Tests/shell_cmds/time
install -o root -g wheel -m 0644 "$SRCROOT"/time/tests/test_time.sh \
"$DSTROOT"/AppleInternal/Tests/shell_cmds/time
install -d -o root -g wheel -m 0755 \
"$DSTROOT"/AppleInternal/CoreOS/BATS/unit_tests
install -o root -g wheel -m 0644 "$SRCROOT"/tests/shell_cmds.plist \
"$DSTROOT"/AppleInternal/CoreOS/BATS/unit_tests
# Skip locate and su targets for iOS
if [ "$TARGET_NAME" = "All_iOS" ]; then
exit 0
@ -50,9 +64,3 @@ echo ".so man8/locate.updatedb.8" > "$MANDIR"/man8/locate.mklocatedb.8
install -d -o root -g wheel -m 0755 "$PAMDIR"
install -c -o root -g wheel -m 0644 "$SRCROOT"/su/su.pam "$PAMDIR"/su
install -d -o root -g wheel -m 0755 "$DSTROOT"/AppleInternal/Tests/shell_cmds
install -o root -g wheel -m 0644 "$SRCROOT"/tests/regress.m4 "$DSTROOT"/AppleInternal/Tests/shell_cmds
install -d -o root -g wheel -m 0755 "$DSTROOT"/AppleInternal/CoreOS/BATS/unit_tests
install -o root -g wheel -m 0644 "$SRCROOT"/tests/shell_cmds.plist "$DSTROOT"/AppleInternal/CoreOS/BATS/unit_tests