diff options
author | sjg <sjg@FreeBSD.org> | 2013-04-12 20:48:55 +0000 |
---|---|---|
committer | sjg <sjg@FreeBSD.org> | 2013-04-12 20:48:55 +0000 |
commit | 97d8b9495668afa398ab17c8c5f7e223b5fd2e89 (patch) | |
tree | 54038c9ac32a45f8741dcc23fb9a8ffc0e15ff89 /bin | |
parent | 5ee3bfdb338e7c80af29a67f4425c4be24c7b866 (diff) | |
parent | 086d73aef6d0ab7d21daa2076fdc8d25961f9b05 (diff) | |
download | FreeBSD-src-97d8b9495668afa398ab17c8c5f7e223b5fd2e89.zip FreeBSD-src-97d8b9495668afa398ab17c8c5f7e223b5fd2e89.tar.gz |
sync from head
Diffstat (limited to 'bin')
-rw-r--r-- | bin/chflags/chflags.c | 6 | ||||
-rw-r--r-- | bin/cp/cp.1 | 23 | ||||
-rw-r--r-- | bin/dd/dd.c | 7 | ||||
-rw-r--r-- | bin/ed/cbc.c | 4 | ||||
-rw-r--r-- | bin/ls/ls.1 | 20 | ||||
-rw-r--r-- | bin/mkdir/mkdir.1 | 19 | ||||
-rw-r--r-- | bin/mv/mv.1 | 12 | ||||
-rw-r--r-- | bin/mv/mv.c | 2 | ||||
-rw-r--r-- | bin/ps/ps.1 | 6 | ||||
-rw-r--r-- | bin/rm/rm.1 | 15 | ||||
-rw-r--r-- | bin/rmdir/rmdir.1 | 14 | ||||
-rw-r--r-- | bin/setfacl/setfacl.1 | 24 | ||||
-rw-r--r-- | bin/sh/eval.c | 6 | ||||
-rw-r--r-- | bin/sh/exec.c | 4 | ||||
-rw-r--r-- | bin/sh/expand.c | 13 | ||||
-rw-r--r-- | bin/sh/input.c | 14 | ||||
-rw-r--r-- | bin/sh/input.h | 4 | ||||
-rw-r--r-- | bin/sh/jobs.c | 14 | ||||
-rw-r--r-- | bin/sh/main.c | 6 | ||||
-rw-r--r-- | bin/sh/memalloc.c | 5 | ||||
-rw-r--r-- | bin/sh/memalloc.h | 4 | ||||
-rw-r--r-- | bin/sh/nodes.c.pat | 6 | ||||
-rw-r--r-- | bin/sh/parser.c | 11 | ||||
-rw-r--r-- | bin/sh/parser.h | 2 | ||||
-rw-r--r-- | bin/sh/redir.c | 18 | ||||
-rw-r--r-- | bin/sh/sh.1 | 15 | ||||
-rw-r--r-- | bin/sh/trap.c | 42 | ||||
-rw-r--r-- | bin/sh/trap.h | 2 | ||||
-rw-r--r-- | bin/test/test.1 | 58 | ||||
-rw-r--r-- | bin/test/test.c | 184 |
30 files changed, 444 insertions, 116 deletions
diff --git a/bin/chflags/chflags.c b/bin/chflags/chflags.c index 2c07db9..e94c34d 100644 --- a/bin/chflags/chflags.c +++ b/bin/chflags/chflags.c @@ -117,11 +117,7 @@ main(int argc, char *argv[]) } else fts_options = hflag ? FTS_PHYSICAL : FTS_LOGICAL; - /* XXX: Why don't chflags and lchflags have compatible prototypes? */ - if (hflag) - change_flags = (int (*)(const char *, unsigned long))lchflags; - else - change_flags = chflags; + change_flags = hflag ? lchflags : chflags; flags = *argv; if (*flags >= '0' && *flags <= '7') { diff --git a/bin/cp/cp.1 b/bin/cp/cp.1 index 8c014b4..169f350 100644 --- a/bin/cp/cp.1 +++ b/bin/cp/cp.1 @@ -32,7 +32,7 @@ .\" @(#)cp.1 8.3 (Berkeley) 4/18/94 .\" $FreeBSD$ .\" -.Dd September 4, 2012 +.Dd March 15, 2013 .Dt CP 1 .Os .Sh NAME @@ -251,6 +251,27 @@ signal, the current input and output file and the percentage complete will be written to the standard output. .Sh EXIT STATUS .Ex -std +.Sh EXAMPLES +Make a copy of file +.Pa foo +named +.Pa bar : +.Pp +.Dl $ cp foo bar +.Pp +Copy a group of files to the +.Pa /tmp +directory: +.Pp +.Dl $ cp *.txt /tmp +.Pp +Copy the directory +.Pa junk +and all of its contents (including any subdirectories) to the +.Pa /tmp +directory: +.Pp +.Dl $ cp -R junk /tmp .Sh COMPATIBILITY Historic versions of the .Nm diff --git a/bin/dd/dd.c b/bin/dd/dd.c index 637e0cc..01b66fc 100644 --- a/bin/dd/dd.c +++ b/bin/dd/dd.c @@ -98,6 +98,13 @@ main(int argc __unused, char *argv[]) dd_in(); dd_close(); + /* + * Some devices such as cfi(4) may perform significant amounts + * of work when a write descriptor is closed. Close the out + * descriptor explicitly so that the summary handler (called + * from an atexit() hook) includes this work. + */ + close(out.fd); exit(0); } diff --git a/bin/ed/cbc.c b/bin/ed/cbc.c index 08e48cd..31838f5 100644 --- a/bin/ed/cbc.c +++ b/bin/ed/cbc.c @@ -71,7 +71,6 @@ __FBSDID("$FreeBSD$"); #ifdef DES static DES_cblock ivec; /* initialization vector */ static DES_cblock pvec; /* padding vector */ -#endif static char bits[] = { /* used to extract bits from a char */ '\200', '\100', '\040', '\020', '\010', '\004', '\002', '\001' @@ -79,13 +78,12 @@ static char bits[] = { /* used to extract bits from a char */ static int pflag; /* 1 to preserve parity bits */ -#ifdef DES static DES_key_schedule schedule; /* expanded DES key */ -#endif static unsigned char des_buf[8];/* shared buffer for get_des_char/put_des_char */ static int des_ct = 0; /* count for get_des_char/put_des_char */ static int des_n = 0; /* index for put_des_char/get_des_char */ +#endif /* init_des_cipher: initialize DES */ void diff --git a/bin/ls/ls.1 b/bin/ls/ls.1 index aa4fc18..7c72652 100644 --- a/bin/ls/ls.1 +++ b/bin/ls/ls.1 @@ -32,7 +32,7 @@ .\" @(#)ls.1 8.7 (Berkeley) 7/29/94 .\" $FreeBSD$ .\" -.Dd November 8, 2012 +.Dd March 15, 2013 .Dt LS 1 .Os .Sh NAME @@ -718,6 +718,24 @@ for more information. .El .Sh EXIT STATUS .Ex -std +.Sh EXAMPLES +List the contents of the current working directory in long format: +.Pp +.Dl $ ls -l +.Pp +In addition to listing the contents of the current working directory in +long format, show inode numbers, file flags (see +.Xr chflags 1 ) , +and suffix each filename with a symbol representing its file type: +.Pp +.Dl $ ls -lioF +.Pp +List the files in +.Pa /var/log , +sorting the output such that the mostly recently modified entries are +printed first: +.Pp +.Dl $ ls -lt /var/log .Sh COMPATIBILITY The group field is now automatically included in the long listing for files in order to be compatible with the diff --git a/bin/mkdir/mkdir.1 b/bin/mkdir/mkdir.1 index 0f8d812..d702348 100644 --- a/bin/mkdir/mkdir.1 +++ b/bin/mkdir/mkdir.1 @@ -32,7 +32,7 @@ .\" @(#)mkdir.1 8.2 (Berkeley) 1/25/94 .\" $FreeBSD$ .\" -.Dd January 25, 1994 +.Dd March 15, 2013 .Dt MKDIR 1 .Os .Sh NAME @@ -87,6 +87,23 @@ Be verbose when creating directories, listing them as they are created. The user must have write permission in the parent directory. .Sh EXIT STATUS .Ex -std +.Sh EXAMPLES +Create a directory named +.Pa foobar : +.Pp +.Dl $ mkdir foobar +.Pp +Create a directory named +.Pa foobar +and set its file mode to 700: +.Pp +.Dl $ mkdir -m 700 foobar +.Pp +Create a directory named +.Pa cow/horse/monkey , +creating any non-existent intermediate directories as necessary: +.Pp +.Dl $ mkdir -p cow/horse/monkey .Sh COMPATIBILITY The .Fl v diff --git a/bin/mv/mv.1 b/bin/mv/mv.1 index 5199f27..298dbf9 100644 --- a/bin/mv/mv.1 +++ b/bin/mv/mv.1 @@ -32,7 +32,7 @@ .\" @(#)mv.1 8.1 (Berkeley) 5/31/93 .\" $FreeBSD$ .\" -.Dd August 28, 2012 +.Dd March 15, 2013 .Dt MV 1 .Os .Sh NAME @@ -155,6 +155,16 @@ rm -rf source_file .Ed .Sh EXIT STATUS .Ex -std +.Sh EXAMPLES +Rename file +.Pa foo +to +.Pa bar , +overwriting +.Pa bar +if it already exists: +.Pp +.Dl $ mv -f foo bar .Sh COMPATIBILITY The .Fl h , diff --git a/bin/mv/mv.c b/bin/mv/mv.c index 5147a2db..2710f89 100644 --- a/bin/mv/mv.c +++ b/bin/mv/mv.c @@ -337,7 +337,7 @@ err: if (unlink(to)) * on a file that we copied, i.e., that we didn't create.) */ errno = 0; - if (fchflags(to_fd, (u_long)sbp->st_flags)) + if (fchflags(to_fd, sbp->st_flags)) if (errno != EOPNOTSUPP || sbp->st_flags != 0) warn("%s: set flags (was: 0%07o)", to, sbp->st_flags); diff --git a/bin/ps/ps.1 b/bin/ps/ps.1 index 7f69137..1a364f5 100644 --- a/bin/ps/ps.1 +++ b/bin/ps/ps.1 @@ -29,7 +29,7 @@ .\" @(#)ps.1 8.3 (Berkeley) 4/18/94 .\" $FreeBSD$ .\" -.Dd February 7, 2013 +.Dd March 15, 2013 .Dt PS 1 .Os .Sh NAME @@ -689,6 +689,10 @@ attempts to automatically determine the terminal width. .It Pa /boot/kernel/kernel default system namelist .El +.Sh EXAMPLES +Display information on all system processes: +.Pp +.Dl $ ps -auxw .Sh SEE ALSO .Xr kill 1 , .Xr pgrep 1 , diff --git a/bin/rm/rm.1 b/bin/rm/rm.1 index ad81066..3588f38 100644 --- a/bin/rm/rm.1 +++ b/bin/rm/rm.1 @@ -32,7 +32,7 @@ .\" @(#)rm.1 8.5 (Berkeley) 12/5/94 .\" $FreeBSD$ .\" -.Dd October 31, 2010 +.Dd March 15, 2013 .Dt RM 1 .Os .Sh NAME @@ -193,6 +193,19 @@ When is specified with .Fl f the file will be overwritten and removed even if it has hard links. +.Sh EXAMPLES +Recursively remove all files contained within the +.Pa foobar +directory hierarchy: +.Pp +.Dl $ rm -rf foobar +.Pp +Either of these commands will remove the file +.Pa -f : +.Bd -literal -offset indent +$ rm -- -f +$ rm ./-f +.Ed .Sh COMPATIBILITY The .Nm diff --git a/bin/rmdir/rmdir.1 b/bin/rmdir/rmdir.1 index 688d144..ededd43 100644 --- a/bin/rmdir/rmdir.1 +++ b/bin/rmdir/rmdir.1 @@ -32,7 +32,7 @@ .\" @(#)rmdir.1 8.1 (Berkeley) 5/31/93 .\" $FreeBSD$ .\" -.Dd March 21, 2004 +.Dd March 15, 2013 .Dt RMDIR 1 .Os .Sh NAME @@ -86,6 +86,18 @@ successfully. .It Li >0 An error occurred. .El +.Sh EXAMPLES +Remove the directory +.Pa foobar , +if it is empty: +.Pp +.Dl $ rmdir foobar +.Pp +Remove all directories up to and including +.Pa cow , +stopping at the first non-empty directory (if any): +.Pp +.Dl $ rmdir -p cow/horse/monkey .Sh SEE ALSO .Xr rm 1 .Sh STANDARDS diff --git a/bin/setfacl/setfacl.1 b/bin/setfacl/setfacl.1 index 3d7b517..4104315 100644 --- a/bin/setfacl/setfacl.1 +++ b/bin/setfacl/setfacl.1 @@ -26,7 +26,7 @@ .\" .\" $FreeBSD$ .\" -.Dd September 2, 2012 +.Dd April 1, 2013 .Dt SETFACL 1 .Os .Sh NAME @@ -91,10 +91,16 @@ An error will be reported if any of the specified files cannot have a default entry (i.e.\& non-directories). This option is not applicable to NFSv4 ACLs. .It Fl m Ar entries -Modify the ACL entries on the specified files by adding new -entries and modifying existing ACL entries with the ACL entries -specified in -.Ar entries . +Modify the ACL on the specified file. +New entries will be added, and existing entries will be modified +according to the +.Ar entries +argument. +For NFSv4 ACLs, it is recommended to use the +.Fl a +and +.Fl x +options instead. .It Fl M Ar file Modify the ACL entries on the specified files by adding new ACL entries and modifying existing ACL entries with the ACL @@ -319,9 +325,9 @@ write_data execute .It p append_data -.It d -delete_child .It D +delete_child +.It d delete .It a read_attributes @@ -395,6 +401,10 @@ NFSv4 ACL entries are evaluated in their visible order. .Pp Multiple ACL entries specified on the command line are separated by commas. +.Pp +Note that the file owner is always granted the read_acl, write_acl, +read_attributes, and write_attributes permissions, even if the ACL +would deny it. .Sh EXIT STATUS .Ex -std .Sh EXAMPLES diff --git a/bin/sh/eval.c b/bin/sh/eval.c index 66ae40e..d3708b3 100644 --- a/bin/sh/eval.c +++ b/bin/sh/eval.c @@ -174,6 +174,7 @@ evalstring(char *s, int flags) any = 1; } popstackmark(&smark); + setstackmark(&smark); } popfile(); popstackmark(&smark); @@ -278,6 +279,8 @@ evaltree(union node *n, int flags) break; case NNOT: evaltree(n->nnot.com, EV_TESTED); + if (evalskip) + goto out; exitstatus = !exitstatus; break; @@ -296,10 +299,11 @@ evaltree(union node *n, int flags) } n = next; popstackmark(&smark); + setstackmark(&smark); } while (n != NULL); out: popstackmark(&smark); - if (pendingsigs) + if (pendingsig) dotrap(); if (eflag && exitstatus != 0 && do_etest) exitshell(exitstatus); diff --git a/bin/sh/exec.c b/bin/sh/exec.c index 7a6dbae..6c3a6dd 100644 --- a/bin/sh/exec.c +++ b/bin/sh/exec.c @@ -165,7 +165,7 @@ tryexec(char *cmd, char **argv, char **envp) } } *argv = cmd; - *--argv = _PATH_BSHELL; + *--argv = __DECONST(char *, _PATH_BSHELL); execve(_PATH_BSHELL, argv, envp); } errno = e; @@ -188,7 +188,7 @@ padvance(const char **path, const char *name) { const char *p, *start; char *q; - int len; + size_t len; if (*path == NULL) return NULL; diff --git a/bin/sh/expand.c b/bin/sh/expand.c index 107f798..414bfa7 100644 --- a/bin/sh/expand.c +++ b/bin/sh/expand.c @@ -460,7 +460,7 @@ expbackq(union node *cmd, int quoted, int flag) int startloc = dest - stackblock(); char const *syntax = quoted? DQSYNTAX : BASESYNTAX; int quotes = flag & (EXP_FULL | EXP_CASE | EXP_REDIR); - int nnl; + size_t nnl; INTOFF; saveifs = ifsfirst; @@ -1163,9 +1163,9 @@ nometa: static void expmeta(char *enddir, char *name) { - char *p; - char *q; - char *start; + const char *p; + const char *q; + const char *start; char *endname; int metaflag; struct stat statb; @@ -1229,7 +1229,7 @@ expmeta(char *enddir, char *name) addfname(expdir); return; } - endname = p; + endname = name + (p - name); if (start != name) { p = name; while (p < start) { @@ -1412,7 +1412,8 @@ match_charclass(const char *p, wchar_t chr, const char **end) *end = NULL; p++; nameend = strstr(p, ":]"); - if (nameend == NULL || nameend - p >= sizeof(name) || nameend == p) + if (nameend == NULL || (size_t)(nameend - p) >= sizeof(name) || + nameend == p) return 0; memcpy(name, p, nameend - p); name[nameend - p] = '\0'; diff --git a/bin/sh/input.c b/bin/sh/input.c index 84580ad..62e82a0 100644 --- a/bin/sh/input.c +++ b/bin/sh/input.c @@ -66,7 +66,7 @@ __FBSDID("$FreeBSD$"); struct strpush { struct strpush *prev; /* preceding string on stack */ - char *prevstring; + const char *prevstring; int prevnleft; int prevlleft; struct alias *ap; /* if push was associated with an alias */ @@ -83,7 +83,7 @@ struct parsefile { int fd; /* file descriptor (or -1 if string) */ int nleft; /* number of chars left in this line */ int lleft; /* number of lines left in this buffer */ - char *nextc; /* next char in buffer */ + const char *nextc; /* next char in buffer */ char *buf; /* input buffer */ struct strpush *strpush; /* for pushing strings at this level */ struct strpush basestrpush; /* so pushing one is fast */ @@ -93,7 +93,7 @@ struct parsefile { int plinno = 1; /* input line number */ int parsenleft; /* copy of parsefile->nleft */ MKINIT int parselleft; /* copy of parsefile->lleft */ -char *parsenextc; /* copy of parsefile->nextc */ +const char *parsenextc; /* copy of parsefile->nextc */ static char basebuf[BUFSIZ + 1];/* buffer for top level input file */ static struct parsefile basepf = { /* top level input file */ .nextc = basebuf, @@ -185,7 +185,7 @@ retry: nr = el_len; if (nr > BUFSIZ) nr = BUFSIZ; - memcpy(parsenextc, rl_cp, nr); + memcpy(parsefile->buf, rl_cp, nr); if (nr != el_len) { el_len -= nr; rl_cp += nr; @@ -194,7 +194,7 @@ retry: } } else #endif - nr = read(parsefile->fd, parsenextc, BUFSIZ); + nr = read(parsefile->fd, parsefile->buf, BUFSIZ); if (nr <= 0) { if (nr < 0) { @@ -252,7 +252,7 @@ again: } } - q = p = parsenextc; + q = p = parsefile->buf + (parsenextc - parsefile->buf); /* delete nul characters */ something = 0; @@ -439,7 +439,7 @@ setinputfd(int fd, int push) */ void -setinputstring(char *string, int push) +setinputstring(const char *string, int push) { INTOFF; if (push) diff --git a/bin/sh/input.h b/bin/sh/input.h index c8802f9..70f675e 100644 --- a/bin/sh/input.h +++ b/bin/sh/input.h @@ -42,7 +42,7 @@ */ extern int plinno; extern int parsenleft; /* number of characters left in input buffer */ -extern char *parsenextc; /* next character in input buffer */ +extern const char *parsenextc; /* next character in input buffer */ struct alias; struct parsefile; @@ -55,7 +55,7 @@ void pungetc(void); void pushstring(char *, int, struct alias *); void setinputfile(const char *, int); void setinputfd(int, int); -void setinputstring(char *, int); +void setinputstring(const char *, int); void popfile(void); struct parsefile *getcurrentfile(void); void popfilesupto(struct parsefile *); diff --git a/bin/sh/jobs.c b/bin/sh/jobs.c index c86394f..c978e3d 100644 --- a/bin/sh/jobs.c +++ b/bin/sh/jobs.c @@ -458,14 +458,15 @@ freejob(struct job *jp) int -waitcmd(int argc, char **argv) +waitcmd(int argc __unused, char **argv __unused) { struct job *job; int status, retval; struct job *jp; - if (argc > 1) { - job = getjob(argv[1]); + nextopt(""); + if (*argptr != NULL) { + job = getjob(*argptr); } else { job = NULL; } @@ -521,7 +522,7 @@ waitcmd(int argc, char **argv) } while (dowait(DOWAIT_BLOCK | DOWAIT_SIG, (struct job *)NULL) != -1); in_waitcmd--; - return 0; + return pendingsig + 128; } @@ -667,7 +668,8 @@ makejob(union node *node __unused, int nprocs) jobtab = jp; } jp = jobtab + njobs; - for (i = 4 ; --i >= 0 ; jobtab[njobs++].used = 0); + for (i = 4 ; --i >= 0 ; jobtab[njobs++].used = 0) + ; INTON; break; } @@ -1004,7 +1006,7 @@ waitforjob(struct job *jp, int *origstatus) static void -dummy_handler(int sig) +dummy_handler(int sig __unused) { } diff --git a/bin/sh/main.c b/bin/sh/main.c index 66e1335..84a1ef2 100644 --- a/bin/sh/main.c +++ b/bin/sh/main.c @@ -80,7 +80,7 @@ struct jmploc main_handler; int localeisutf8, initial_localeisutf8; static void cmdloop(int); -static void read_profile(char *); +static void read_profile(const char *); static char *find_dot_file(char *); /* @@ -196,7 +196,7 @@ cmdloop(int top) TRACE(("cmdloop(%d) called\n", top)); setstackmark(&smark); for (;;) { - if (pendingsigs) + if (pendingsig) dotrap(); inter = 0; if (iflag && top) { @@ -239,7 +239,7 @@ cmdloop(int top) */ static void -read_profile(char *name) +read_profile(const char *name) { int fd; const char *expandedname; diff --git a/bin/sh/memalloc.c b/bin/sh/memalloc.c index bc567d0..f33a15c 100644 --- a/bin/sh/memalloc.c +++ b/bin/sh/memalloc.c @@ -233,7 +233,8 @@ growstackblock(int min) if (min < stacknleft) min = stacknleft; - if (min >= INT_MAX / 2 - ALIGN(sizeof(struct stack_block))) + if ((unsigned int)min >= + INT_MAX / 2 - ALIGN(sizeof(struct stack_block))) error("Out of space"); min += stacknleft; min += ALIGN(sizeof(struct stack_block)); @@ -327,7 +328,7 @@ makestrspace(int min, char *p) char * -stputbin(const char *data, int len, char *p) +stputbin(const char *data, size_t len, char *p) { CHECKSTRSPACE(len, p); memcpy(p, data, len); diff --git a/bin/sh/memalloc.h b/bin/sh/memalloc.h index 425004e..95a6594 100644 --- a/bin/sh/memalloc.h +++ b/bin/sh/memalloc.h @@ -57,7 +57,7 @@ void setstackmark(struct stackmark *); void popstackmark(struct stackmark *); char *growstackstr(void); char *makestrspace(int, char *); -char *stputbin(const char *data, int len, char *p); +char *stputbin(const char *data, size_t len, char *p); char *stputs(const char *data, char *p); @@ -67,7 +67,7 @@ char *stputs(const char *data, char *p); #define grabstackblock(n) stalloc(n) #define STARTSTACKSTR(p) p = stackblock() #define STPUTC(c, p) do { if (p == sstrend) p = growstackstr(); *p++ = (c); } while(0) -#define CHECKSTRSPACE(n, p) { if (sstrend - p < n) p = makestrspace(n, p); } +#define CHECKSTRSPACE(n, p) { if ((size_t)(sstrend - p) < n) p = makestrspace(n, p); } #define USTPUTC(c, p) (*p++ = (c)) /* * STACKSTRNUL's use is where we want to be able to turn a stack diff --git a/bin/sh/nodes.c.pat b/bin/sh/nodes.c.pat index b325d76..e99e3ab 100644 --- a/bin/sh/nodes.c.pat +++ b/bin/sh/nodes.c.pat @@ -58,7 +58,7 @@ static void calcsize(union node *); static void sizenodelist(struct nodelist *); static union node *copynode(union node *); static struct nodelist *copynodelist(struct nodelist *); -static char *nodesavestr(char *); +static char *nodesavestr(const char *); struct funcdef { @@ -147,9 +147,9 @@ copynodelist(struct nodelist *lp) static char * -nodesavestr(char *s) +nodesavestr(const char *s) { - char *p = s; + const char *p = s; char *q = funcstring; char *rtn = funcstring; diff --git a/bin/sh/parser.c b/bin/sh/parser.c index 665b53f..073c2b6 100644 --- a/bin/sh/parser.c +++ b/bin/sh/parser.c @@ -119,7 +119,7 @@ static void parseheredoc(void); static int peektoken(void); static int readtoken(void); static int xxreadtoken(void); -static int readtoken1(int, char const *, char *, int); +static int readtoken1(int, const char *, const char *, int); static int noexpand(char *); static void synexpect(int) __dead2; static void synerror(const char *) __dead2; @@ -983,7 +983,7 @@ parsebackq(char *out, struct nodelist **pbqlist, char *volatile str; struct jmploc jmploc; struct jmploc *const savehandler = handler; - int savelen; + size_t savelen; int saveprompt; const int bq_startlinno = plinno; char *volatile ostr = NULL; @@ -1300,7 +1300,8 @@ readcstyleesc(char *out) #define PARSEARITH() {goto parsearith; parsearith_return:;} static int -readtoken1(int firstc, char const *initialsyntax, char *eofmark, int striptabs) +readtoken1(int firstc, char const *initialsyntax, const char *eofmark, + int striptabs) { int c = firstc; char *out; @@ -1521,7 +1522,7 @@ checkend: { } if (c == *eofmark) { if (pfgets(line, sizeof line) != NULL) { - char *p, *q; + const char *p, *q; p = line; for (q = eofmark + 1 ; *q && *p == *q ; p++, q++); @@ -2038,7 +2039,7 @@ getprompt(void *unused __unused) const char * -expandstr(char *ps) +expandstr(const char *ps) { union node n; struct jmploc jmploc; diff --git a/bin/sh/parser.h b/bin/sh/parser.h index f80d917..b803f76 100644 --- a/bin/sh/parser.h +++ b/bin/sh/parser.h @@ -82,4 +82,4 @@ void fixredir(union node *, const char *, int); int goodname(const char *); int isassignment(const char *); char *getprompt(void *); -const char *expandstr(char *); +const char *expandstr(const char *); diff --git a/bin/sh/redir.c b/bin/sh/redir.c index c11cb71..fda094d2 100644 --- a/bin/sh/redir.c +++ b/bin/sh/redir.c @@ -64,7 +64,6 @@ __FBSDID("$FreeBSD$"); #define EMPTY -2 /* marks an unused slot in redirtab */ #define CLOSED -1 /* fd was not open before redir */ -#define PIPESIZE 4096 /* amount of buffering in a pipe */ MKINIT @@ -253,7 +252,9 @@ openhere(union node *redir) { char *p; int pip[2]; - int len = 0; + size_t len = 0; + int flags; + ssize_t written = 0; if (pipe(pip) < 0) error("Pipe call failed: %s", strerror(errno)); @@ -263,9 +264,16 @@ openhere(union node *redir) else p = redir->nhere.doc->narg.text; len = strlen(p); - if (len <= PIPESIZE) { - xwrite(pip[1], p, len); + if (len == 0) goto out; + flags = fcntl(pip[1], F_GETFL, 0); + if (flags != -1 && fcntl(pip[1], F_SETFL, flags | O_NONBLOCK) != -1) { + written = write(pip[1], p, len); + if (written < 0) + written = 0; + if ((size_t)written == len) + goto out; + fcntl(pip[1], F_SETFL, flags); } if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) { @@ -275,7 +283,7 @@ openhere(union node *redir) signal(SIGHUP, SIG_IGN); signal(SIGTSTP, SIG_IGN); signal(SIGPIPE, SIG_DFL); - xwrite(pip[1], p, len); + xwrite(pip[1], p + written, len - written); _exit(0); } out: diff --git a/bin/sh/sh.1 b/bin/sh/sh.1 index 09d94f3..01cb775 100644 --- a/bin/sh/sh.1 +++ b/bin/sh/sh.1 @@ -32,7 +32,7 @@ .\" from: @(#)sh.1 8.6 (Berkeley) 5/4/95 .\" $FreeBSD$ .\" -.Dd January 22, 2013 +.Dd March 24, 2013 .Dt SH 1 .Os .Sh NAME @@ -1061,6 +1061,9 @@ A subshell environment may be implemented as a child process or differently. If job control is enabled in an interactive shell, commands grouped in parentheses can be suspended and continued as a unit. .Pp +For compatibility with other shells, +two open parentheses in sequence should be separated by whitespace. +.Pp The second form never forks another shell, so it is slightly more efficient. Grouping commands together this way allows the user to @@ -1618,6 +1621,16 @@ and .Ic times returns information about the same process if they are the only command in a command substitution. +.Pp +If a command substitution of the +.Li $( +form begins with a subshell, +the +.Li $( +and +.Li (\& +must be separated by whitespace +to avoid ambiguity with arithmetic expansion. .Ss Arithmetic Expansion Arithmetic expansion provides a mechanism for evaluating an arithmetic expression and substituting its value. diff --git a/bin/sh/trap.c b/bin/sh/trap.c index 521c511..3138029 100644 --- a/bin/sh/trap.c +++ b/bin/sh/trap.c @@ -73,7 +73,7 @@ __FBSDID("$FreeBSD$"); MKINIT char sigmode[NSIG]; /* current value of signal */ -int pendingsigs; /* indicates some signal received */ +volatile sig_atomic_t pendingsig; /* indicates some signal received */ int in_dotrap; /* do we execute in a trap handler? */ static char *volatile trap[NSIG]; /* trap handler commands */ static volatile sig_atomic_t gotsig[NSIG]; @@ -150,7 +150,7 @@ printsignals(void) * The trap builtin. */ int -trapcmd(int argc, char **argv) +trapcmd(int argc __unused, char **argv) { char *action; int signo; @@ -388,22 +388,25 @@ onsig(int signo) return; } - if (signo != SIGCHLD || !ignore_sigchld) - gotsig[signo] = 1; - pendingsigs++; - /* If we are currently in a wait builtin, prepare to break it */ - if ((signo == SIGINT || signo == SIGQUIT) && in_waitcmd != 0) - breakwaitcmd = 1; - /* - * If a trap is set, not ignored and not the null command, we need - * to make sure traps are executed even when a child blocks signals. - */ - if (Tflag && - trap[signo] != NULL && - ! (trap[signo][0] == '\0') && - ! (trap[signo][0] == ':' && trap[signo][1] == '\0')) + if ((signo == SIGINT || signo == SIGQUIT) && in_waitcmd != 0) { breakwaitcmd = 1; + pendingsig = signo; + } + + if (trap[signo] != NULL && trap[signo][0] != '\0' && + (signo != SIGCHLD || !ignore_sigchld)) { + gotsig[signo] = 1; + pendingsig = signo; + + /* + * If a trap is set, not ignored and not the null command, we + * need to make sure traps are executed even when a child + * blocks signals. + */ + if (Tflag && !(trap[signo][0] == ':' && trap[signo][1] == '\0')) + breakwaitcmd = 1; + } #ifndef NO_HISTORY if (signo == SIGWINCH) @@ -424,7 +427,7 @@ dotrap(void) in_dotrap++; for (;;) { - pendingsigs = 0; + pendingsig = 0; for (i = 1; i < NSIG; i++) { if (gotsig[i]) { gotsig[i] = 0; @@ -452,7 +455,6 @@ dotrap(void) last_trapsig = i; savestatus = exitstatus; evalstring(trap[i], 0); - exitstatus = savestatus; /* * If such a command was not @@ -461,9 +463,11 @@ dotrap(void) * trap action to have an effect * outside of it. */ - if (prev_evalskip != 0) { + if (evalskip == 0 || + prev_evalskip != 0) { evalskip = prev_evalskip; skipcount = prev_skipcount; + exitstatus = savestatus; } if (i == SIGCHLD) diff --git a/bin/sh/trap.h b/bin/sh/trap.h index 61a17ec..0a05d8d 100644 --- a/bin/sh/trap.h +++ b/bin/sh/trap.h @@ -33,7 +33,7 @@ * $FreeBSD$ */ -extern int pendingsigs; +extern volatile sig_atomic_t pendingsig; extern int in_dotrap; extern volatile sig_atomic_t gotwinch; diff --git a/bin/test/test.1 b/bin/test/test.1 index 885374e..76a4a9c 100644 --- a/bin/test/test.1 +++ b/bin/test/test.1 @@ -169,15 +169,65 @@ True if .Ar file exists and is a socket. .It Ar file1 Fl nt Ar file2 -True if +True if both +.Ar file1 +and +.Ar file2 +exist and +.Ar file1 +is newer than +.Ar file2 . +.It Ar file1 Fl nt Ns Ar X Ns Ar Y Ar file2 +True if both +.Ar file1 +and +.Ar file2 +exist and .Ar file1 -exists and is newer than +has a more recent last access time +.Pq Ar X Ns = Ns Cm a , +inode creation time +.Pq Ar X Ns = Ns Cm b , +change time +.Pq Ar X Ns = Ns Cm c , +or modification time +.Pq Ar X Ns = Ns Cm m +than the last access time +.Pq Ar Y Ns = Ns Cm a , +inode creation time +.Pq Ar Y Ns = Ns Cm b , +change time +.Pq Ar Y Ns = Ns Cm c , +or modification time +.Pq Ar Y Ns = Ns Cm m +of .Ar file2 . +Note that +.Ic -ntmm +is equivalent to +.Ic -nt . .It Ar file1 Fl ot Ar file2 -True if +True if both +.Ar file1 +and +.Ar file2 +exist and .Ar file1 -exists and is older than +is older than .Ar file2 . +Note that +.Ar file1 +.Ic -ot +.Ar file2 +is equivalent to +.Ar file2 +.Ic -nt +.Ar file1 +.It Ar file1 Fl ot Ns Ar X Ns Ar Y Ar file2 +Equivalent to +.Ar file2 +.Ic -nt Ns Ar Y Ns Ar X +.Ar file1 . .It Ar file1 Fl ef Ar file2 True if .Ar file1 diff --git a/bin/test/test.c b/bin/test/test.c index 96aa9f5..eaa2f40 100644 --- a/bin/test/test.c +++ b/bin/test/test.c @@ -63,7 +63,7 @@ error(const char *msg, ...) "-u"|"-g"|"-k"|"-s"|"-t"|"-z"|"-n"|"-o"|"-O"|"-G"|"-L"|"-S"; binary-operator ::= "="|"!="|"-eq"|"-ne"|"-ge"|"-gt"|"-le"|"-lt"| - "-nt"|"-ot"|"-ef"; + "-nt"|"-nt[abcm][abcm]"|"-ot"|"-ot[abcm][abcm])"|"-ef"; operand ::= <any legal UNIX file name> */ @@ -85,8 +85,38 @@ enum token { FILSUID, FILSGID, FILSTCK, - FILNT, - FILOT, + FILNTAA, + FILNTAB, + FILNTAC, + FILNTAM, + FILNTBA, + FILNTBB, + FILNTBC, + FILNTBM, + FILNTCA, + FILNTCB, + FILNTCC, + FILNTCM, + FILNTMA, + FILNTMB, + FILNTMC, + FILNTMM, + FILOTAA, + FILOTAB, + FILOTAC, + FILOTAM, + FILOTBA, + FILOTBB, + FILOTBC, + FILOTBM, + FILOTCA, + FILOTCB, + FILOTCC, + FILOTCM, + FILOTMA, + FILOTMB, + FILOTMC, + FILOTMM, FILEQ, FILUID, FILGID, @@ -118,9 +148,16 @@ enum token_types { PAREN }; +enum time_types { + ATIME, + BTIME, + CTIME, + MTIME +}; + static struct t_op { - char op_text[4]; - short op_num, op_type; + char op_text[6]; + char op_num, op_type; } const ops [] = { {"-r", FILRD, UNOP}, {"-w", FILWR, UNOP}, @@ -154,8 +191,40 @@ static struct t_op { {"-gt", INTGT, BINOP}, {"-le", INTLE, BINOP}, {"-lt", INTLT, BINOP}, - {"-nt", FILNT, BINOP}, - {"-ot", FILOT, BINOP}, + {"-nt", FILNTMM, BINOP}, + {"-ntaa", FILNTAA, BINOP}, + {"-ntab", FILNTAB, BINOP}, + {"-ntac", FILNTAC, BINOP}, + {"-ntam", FILNTAM, BINOP}, + {"-ntba", FILNTBA, BINOP}, + {"-ntbb", FILNTBB, BINOP}, + {"-ntbc", FILNTBC, BINOP}, + {"-ntbm", FILNTBM, BINOP}, + {"-ntca", FILNTCA, BINOP}, + {"-ntcb", FILNTCB, BINOP}, + {"-ntcc", FILNTCC, BINOP}, + {"-ntcm", FILNTCM, BINOP}, + {"-ntma", FILNTMA, BINOP}, + {"-ntmb", FILNTMB, BINOP}, + {"-ntmc", FILNTMC, BINOP}, + {"-ntmm", FILNTMM, BINOP}, + {"-ot", FILOTMM, BINOP}, + {"-otaa", FILOTAA, BINOP}, + {"-otab", FILOTBB, BINOP}, + {"-otac", FILOTAC, BINOP}, + {"-otam", FILOTAM, BINOP}, + {"-otba", FILOTBA, BINOP}, + {"-otbb", FILOTBB, BINOP}, + {"-otbc", FILOTBC, BINOP}, + {"-otbm", FILOTBM, BINOP}, + {"-otca", FILOTCA, BINOP}, + {"-otcb", FILOTCB, BINOP}, + {"-otcc", FILOTCC, BINOP}, + {"-otcm", FILOTCM, BINOP}, + {"-otma", FILOTMA, BINOP}, + {"-otmb", FILOTMB, BINOP}, + {"-otmc", FILOTMC, BINOP}, + {"-otmm", FILOTMM, BINOP}, {"-ef", FILEQ, BINOP}, {"!", UNOT, BUNOP}, {"-a", BAND, BBINOP}, @@ -180,10 +249,10 @@ static int intcmp(const char *, const char *); static int isunopoperand(void); static int islparenoperand(void); static int isrparenoperand(void); -static int newerf(const char *, const char *); +static int newerf(const char *, const char *, enum time_types, + enum time_types); static int nexpr(enum token); static int oexpr(enum token); -static int olderf(const char *, const char *); static int primary(enum token); static void syntax(const char *, const char *); static enum token t_lex(char *); @@ -353,10 +422,70 @@ binop(void) return intcmp(opnd1, opnd2) <= 0; case INTLT: return intcmp(opnd1, opnd2) < 0; - case FILNT: - return newerf (opnd1, opnd2); - case FILOT: - return olderf (opnd1, opnd2); + case FILNTAA: + return newerf(opnd1, opnd2, ATIME, ATIME); + case FILNTAB: + return newerf(opnd1, opnd2, ATIME, BTIME); + case FILNTAC: + return newerf(opnd1, opnd2, ATIME, CTIME); + case FILNTAM: + return newerf(opnd1, opnd2, ATIME, MTIME); + case FILNTBA: + return newerf(opnd1, opnd2, BTIME, ATIME); + case FILNTBB: + return newerf(opnd1, opnd2, BTIME, BTIME); + case FILNTBC: + return newerf(opnd1, opnd2, BTIME, CTIME); + case FILNTBM: + return newerf(opnd1, opnd2, BTIME, MTIME); + case FILNTCA: + return newerf(opnd1, opnd2, CTIME, ATIME); + case FILNTCB: + return newerf(opnd1, opnd2, CTIME, BTIME); + case FILNTCC: + return newerf(opnd1, opnd2, CTIME, CTIME); + case FILNTCM: + return newerf(opnd1, opnd2, CTIME, MTIME); + case FILNTMA: + return newerf(opnd1, opnd2, MTIME, ATIME); + case FILNTMB: + return newerf(opnd1, opnd2, MTIME, BTIME); + case FILNTMC: + return newerf(opnd1, opnd2, MTIME, CTIME); + case FILNTMM: + return newerf(opnd1, opnd2, MTIME, MTIME); + case FILOTAA: + return newerf(opnd2, opnd1, ATIME, ATIME); + case FILOTAB: + return newerf(opnd2, opnd1, BTIME, ATIME); + case FILOTAC: + return newerf(opnd2, opnd1, CTIME, ATIME); + case FILOTAM: + return newerf(opnd2, opnd1, MTIME, ATIME); + case FILOTBA: + return newerf(opnd2, opnd1, ATIME, BTIME); + case FILOTBB: + return newerf(opnd2, opnd1, BTIME, BTIME); + case FILOTBC: + return newerf(opnd2, opnd1, CTIME, BTIME); + case FILOTBM: + return newerf(opnd2, opnd1, MTIME, BTIME); + case FILOTCA: + return newerf(opnd2, opnd1, ATIME, CTIME); + case FILOTCB: + return newerf(opnd2, opnd1, BTIME, CTIME); + case FILOTCC: + return newerf(opnd2, opnd1, CTIME, CTIME); + case FILOTCM: + return newerf(opnd2, opnd1, MTIME, CTIME); + case FILOTMA: + return newerf(opnd2, opnd1, ATIME, MTIME); + case FILOTMB: + return newerf(opnd2, opnd1, BTIME, MTIME); + case FILOTMC: + return newerf(opnd2, opnd1, CTIME, MTIME); + case FILOTMM: + return newerf(opnd2, opnd1, MTIME, MTIME); case FILEQ: return equalf (opnd1, opnd2); default: @@ -570,25 +699,34 @@ intcmp (const char *s1, const char *s2) } static int -newerf (const char *f1, const char *f2) +newerf (const char *f1, const char *f2, enum time_types t1, enum time_types t2) { struct stat b1, b2; + struct timespec *ts1, *ts2; if (stat(f1, &b1) != 0 || stat(f2, &b2) != 0) return 0; - if (b1.st_mtim.tv_sec > b2.st_mtim.tv_sec) + switch (t1) { + case ATIME: ts1 = &b1.st_atim; break; + case BTIME: ts1 = &b1.st_birthtim; break; + case CTIME: ts1 = &b1.st_ctim; break; + default: ts1 = &b1.st_mtim; break; + } + + switch (t2) { + case ATIME: ts2 = &b2.st_atim; break; + case BTIME: ts2 = &b2.st_birthtim; break; + case CTIME: ts2 = &b2.st_ctim; break; + default: ts2 = &b2.st_mtim; break; + } + + if (ts1->tv_sec > ts2->tv_sec) return 1; - if (b1.st_mtim.tv_sec < b2.st_mtim.tv_sec) + if (ts1->tv_sec < ts2->tv_sec) return 0; - return (b1.st_mtim.tv_nsec > b2.st_mtim.tv_nsec); -} - -static int -olderf (const char *f1, const char *f2) -{ - return (newerf(f2, f1)); + return (ts1->tv_nsec > ts2->tv_nsec); } static int |