summaryrefslogtreecommitdiffstats
path: root/bin
diff options
context:
space:
mode:
authorobrien <obrien@FreeBSD.org>2013-02-08 16:10:16 +0000
committerobrien <obrien@FreeBSD.org>2013-02-08 16:10:16 +0000
commit3028e3f8aba938dfd0bf9fda987b8a72140b8027 (patch)
treeb2f038222ff8a70f687652441df00d2b564c8abe /bin
parent952a6d5a7cd3d3f9007acfa06805262fc04a105f (diff)
parent1d08d5f677c1dfa810e381073590adbae19cc69f (diff)
downloadFreeBSD-src-3028e3f8aba938dfd0bf9fda987b8a72140b8027.zip
FreeBSD-src-3028e3f8aba938dfd0bf9fda987b8a72140b8027.tar.gz
Sync with HEAD.
Diffstat (limited to 'bin')
-rw-r--r--bin/cat/cat.117
-rw-r--r--bin/cat/cat.c19
-rw-r--r--bin/cp/cp.c12
-rw-r--r--bin/cp/utils.c19
-rw-r--r--bin/date/netdate.c2
-rw-r--r--bin/df/df.1112
-rw-r--r--bin/df/df.c47
-rw-r--r--bin/ln/ln.12
-rw-r--r--bin/ls/cmp.c20
-rw-r--r--bin/ls/extern.h12
-rw-r--r--bin/ls/ls.172
-rw-r--r--bin/ls/ls.c106
-rw-r--r--bin/ls/ls.h4
-rw-r--r--bin/ls/print.c4
-rw-r--r--bin/ls/util.c19
-rw-r--r--bin/mv/mv.c2
-rw-r--r--bin/ps/extern.h2
-rw-r--r--bin/ps/fmt.c13
-rw-r--r--bin/ps/ps.13
-rw-r--r--bin/ps/ps.c31
-rw-r--r--bin/pwait/pwait.c2
-rw-r--r--bin/sh/TOUR4
-rw-r--r--bin/sh/alias.c11
-rw-r--r--bin/sh/eval.c60
-rw-r--r--bin/sh/exec.c56
-rw-r--r--bin/sh/expand.c13
-rw-r--r--bin/sh/expand.h1
-rw-r--r--bin/sh/init.h1
-rw-r--r--bin/sh/input.c22
-rw-r--r--bin/sh/input.h4
-rw-r--r--bin/sh/jobs.c27
-rw-r--r--bin/sh/main.c2
-rw-r--r--bin/sh/miscbltin.c4
-rw-r--r--bin/sh/mkinit.c8
-rw-r--r--bin/sh/mksyntax.c205
-rw-r--r--bin/sh/nodetypes1
-rw-r--r--bin/sh/output.c14
-rw-r--r--bin/sh/output.h2
-rw-r--r--bin/sh/parser.c7
-rw-r--r--bin/sh/parser.h2
-rw-r--r--bin/sh/redir.c22
-rw-r--r--bin/sh/sh.124
-rw-r--r--bin/sh/var.c32
-rw-r--r--bin/test/test.19
44 files changed, 617 insertions, 434 deletions
diff --git a/bin/cat/cat.1 b/bin/cat/cat.1
index 4fdff3a..69f5ef6 100644
--- a/bin/cat/cat.1
+++ b/bin/cat/cat.1
@@ -32,7 +32,7 @@
.\" @(#)cat.1 8.3 (Berkeley) 5/2/95
.\" $FreeBSD$
.\"
-.Dd March 21, 2004
+.Dd January 29, 2013
.Dt CAT 1
.Os
.Sh NAME
@@ -40,7 +40,7 @@
.Nd concatenate and print files
.Sh SYNOPSIS
.Nm
-.Op Fl benstuv
+.Op Fl belnstuv
.Op Ar
.Sh DESCRIPTION
The
@@ -79,6 +79,16 @@ Display non-printing characters (see the
option), and display a dollar sign
.Pq Ql \&$
at the end of each line.
+.It Fl l
+Set an exclusive advisory lock on the standard output file descriptor.
+This lock is set using
+.Xr fcntl 2
+with the
+.Dv F_SETLKW
+command.
+If the output file is already locked,
+.Nm
+will block until the lock is acquired.
.It Fl n
Number the output lines, starting at 1.
.It Fl s
@@ -160,6 +170,7 @@ operand.
.Xr tail 1 ,
.Xr vis 1 ,
.Xr zcat 1 ,
+.Xr fcntl 2 ,
.Xr setbuf 3
.Rs
.%A Rob Pike
@@ -175,7 +186,7 @@ utility is compliant with the
specification.
.Pp
The flags
-.Op Fl benstv
+.Op Fl belnstv
are extensions to the specification.
.Sh HISTORY
A
diff --git a/bin/cat/cat.c b/bin/cat/cat.c
index 69c56c0..9e12d3e 100644
--- a/bin/cat/cat.c
+++ b/bin/cat/cat.c
@@ -64,7 +64,7 @@ __FBSDID("$FreeBSD$");
#include <string.h>
#include <unistd.h>
-static int bflag, eflag, nflag, sflag, tflag, vflag;
+static int bflag, eflag, lflag, nflag, sflag, tflag, vflag;
static int rval;
static const char *filename;
@@ -96,10 +96,11 @@ int
main(int argc, char *argv[])
{
int ch;
+ struct flock stdout_lock;
setlocale(LC_CTYPE, "");
- while ((ch = getopt(argc, argv, "benstuv")) != -1)
+ while ((ch = getopt(argc, argv, "belnstuv")) != -1)
switch (ch) {
case 'b':
bflag = nflag = 1; /* -b implies -n */
@@ -107,6 +108,9 @@ main(int argc, char *argv[])
case 'e':
eflag = vflag = 1; /* -e implies -v */
break;
+ case 'l':
+ lflag = 1;
+ break;
case 'n':
nflag = 1;
break;
@@ -127,6 +131,15 @@ main(int argc, char *argv[])
}
argv += optind;
+ if (lflag) {
+ stdout_lock.l_len = 0;
+ stdout_lock.l_start = 0;
+ stdout_lock.l_type = F_WRLCK;
+ stdout_lock.l_whence = SEEK_SET;
+ if (fcntl(STDOUT_FILENO, F_SETLKW, &stdout_lock) == -1)
+ err(EXIT_FAILURE, "stdout");
+ }
+
if (bflag || eflag || nflag || sflag || tflag || vflag)
scanfiles(argv, 1);
else
@@ -140,7 +153,7 @@ main(int argc, char *argv[])
static void
usage(void)
{
- fprintf(stderr, "usage: cat [-benstuv] [file ...]\n");
+ fprintf(stderr, "usage: cat [-belnstuv] [file ...]\n");
exit(1);
/* NOTREACHED */
}
diff --git a/bin/cp/cp.c b/bin/cp/cp.c
index 86dbb3c..b83eead 100644
--- a/bin/cp/cp.c
+++ b/bin/cp/cp.c
@@ -98,30 +98,28 @@ main(int argc, char *argv[])
{
struct stat to_stat, tmp_stat;
enum op type;
- int Hflag, Lflag, Pflag, ch, fts_options, r, have_trailing_slash;
+ int Hflag, Lflag, ch, fts_options, r, have_trailing_slash;
char *target;
fts_options = FTS_NOCHDIR | FTS_PHYSICAL;
- Hflag = Lflag = Pflag = 0;
+ Hflag = Lflag = 0;
while ((ch = getopt(argc, argv, "HLPRafilnprvx")) != -1)
switch (ch) {
case 'H':
Hflag = 1;
- Lflag = Pflag = 0;
+ Lflag = 0;
break;
case 'L':
Lflag = 1;
- Hflag = Pflag = 0;
+ Hflag = 0;
break;
case 'P':
- Pflag = 1;
Hflag = Lflag = 0;
break;
case 'R':
Rflag = 1;
break;
case 'a':
- Pflag = 1;
pflag = 1;
Rflag = 1;
Hflag = Lflag = 0;
@@ -146,7 +144,7 @@ main(int argc, char *argv[])
break;
case 'r':
rflag = Lflag = 1;
- Hflag = Pflag = 0;
+ Hflag = 0;
break;
case 'v':
vflag = 1;
diff --git a/bin/cp/utils.c b/bin/cp/utils.c
index d729bd5..ad9695c 100644
--- a/bin/cp/utils.c
+++ b/bin/cp/utils.c
@@ -104,7 +104,7 @@ copy_file(const FTSENT *entp, int dne)
if (vflag)
printf("%s not overwritten\n", to.p_path);
(void)close(from_fd);
- return (0);
+ return (1);
} else if (iflag) {
(void)fprintf(stderr, "overwrite %s? %s",
to.p_path, YESNO);
@@ -266,6 +266,11 @@ copy_link(const FTSENT *p, int exists)
int len;
char llink[PATH_MAX];
+ if (exists && nflag) {
+ if (vflag)
+ printf("%s not overwritten\n", to.p_path);
+ return (1);
+ }
if ((len = readlink(p->fts_path, llink, sizeof(llink) - 1)) == -1) {
warn("readlink: %s", p->fts_path);
return (1);
@@ -285,6 +290,12 @@ copy_link(const FTSENT *p, int exists)
int
copy_fifo(struct stat *from_stat, int exists)
{
+
+ if (exists && nflag) {
+ if (vflag)
+ printf("%s not overwritten\n", to.p_path);
+ return (1);
+ }
if (exists && unlink(to.p_path)) {
warn("unlink: %s", to.p_path);
return (1);
@@ -299,6 +310,12 @@ copy_fifo(struct stat *from_stat, int exists)
int
copy_special(struct stat *from_stat, int exists)
{
+
+ if (exists && nflag) {
+ if (vflag)
+ printf("%s not overwritten\n", to.p_path);
+ return (1);
+ }
if (exists && unlink(to.p_path)) {
warn("unlink: %s", to.p_path);
return (1);
diff --git a/bin/date/netdate.c b/bin/date/netdate.c
index b085be4..e506e6d 100644
--- a/bin/date/netdate.c
+++ b/bin/date/netdate.c
@@ -85,7 +85,7 @@ netsettime(time_t tval)
dest.sin_addr.s_addr = htonl((u_long)INADDR_ANY);
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s < 0) {
- if (errno != EPROTONOSUPPORT)
+ if (errno != EAFNOSUPPORT)
warn("timed");
return (retval = 2);
}
diff --git a/bin/df/df.1 b/bin/df/df.1
index 3c60b26..8d14248 100644
--- a/bin/df/df.1
+++ b/bin/df/df.1
@@ -29,7 +29,7 @@
.\" @(#)df.1 8.3 (Berkeley) 5/8/95
.\" $FreeBSD$
.\"
-.Dd March 3, 2012
+.Dd January 24, 2013
.Dt DF 1
.Os
.Sh NAME
@@ -39,6 +39,7 @@
.Nm
.Op Fl b | g | H | h | k | m | P
.Op Fl acilnT
+.Op Fl \&,
.Op Fl t Ar type
.Op Ar file | filesystem ...
.Sh DESCRIPTION
@@ -50,7 +51,8 @@ displays statistics about the amount of free disk space on the specified
or on the file system of which
.Ar file
is a part.
-Values are displayed in 512-byte per block counts.
+By default block counts are displayed with an assumed block size of
+512 bytes.
If neither a file or a file system operand is specified,
statistics for all mounted file systems are displayed
(subject to the
@@ -65,48 +67,54 @@ Show all mount points, including those that were mounted with the
flag.
This is implied for file systems specified on the command line.
.It Fl b
-Use 512-byte blocks rather than the default.
-Note that
-this overrides the
+Explicitly use 512 byte blocks, overriding any
.Ev BLOCKSIZE
specification from the environment.
+This is the same as the
+.Fl P
+option.
+The
+.Fl k
+option overrides this option.
.It Fl c
Display a grand total.
.It Fl g
-Use 1073741824-byte (1-Gbyte) blocks rather than the default.
-Note that
-this overrides the
+Use 1073741824 byte (1 Gibibyte) blocks rather than the default.
+This overrides any
.Ev BLOCKSIZE
specification from the environment.
.It Fl H
.Dq Human-readable
output.
-Use unit suffixes: Byte, Kilobyte, Megabyte,
-Gigabyte, Terabyte and Petabyte in order to reduce the number of
-digits to four or fewer using base 10 for sizes.
+Use unit suffixes: Byte, Kibibyte, Mebibyte, Gibibyte, Tebibyte and
+Pebibyte (based on powers of 1024) in order to reduce the number of
+digits to four or fewer.
.It Fl h
.Dq Human-readable
output.
Use unit suffixes: Byte, Kilobyte, Megabyte,
-Gigabyte, Terabyte and Petabyte in order to reduce the number of
-digits to four or fewer using base 2 for sizes.
-Inodes statistics, if enabled with
-.Fl i ,
-are always printed in base 10.
+Gigabyte, Terabyte and Petabyte (based on powers of 1000) in order to
+reduce the number of
+digits to four or fewer.
.It Fl i
-Include statistics on the number of free inodes.
+Include statistics on the number of free and used inodes.
+In conjunction with the
+.Fl h
+or
+.Fl H
+options, the number of inodes is scaled by powers of 1000.
.It Fl k
-Use 1024-byte (1-Kbyte) blocks rather than the default.
-Note that
-this overrides the
+Use 1024 byte (1 Kibibyte) blocks rather than the default.
+This overrides the
+.Fl P
+option and any
.Ev BLOCKSIZE
specification from the environment.
.It Fl l
Only display information about locally-mounted file systems.
.It Fl m
-Use 1048576-byte (1-Mbyte) blocks rather than the default.
-Note that
-this overrides the
+Use 1048576 byte (1 Mebibyte) blocks rather than the default.
+This overrides any
.Ev BLOCKSIZE
specification from the environment.
.It Fl n
@@ -119,10 +127,15 @@ When this option is specified,
will not request new statistics from the file systems, but will respond
with the possibly stale statistics that were previously obtained.
.It Fl P
-Use POSIX compliant output of 512-byte blocks rather than the default.
-Note that this overrides the
+Explicitly use 512 byte blocks, overriding any
.Ev BLOCKSIZE
specification from the environment.
+This is the same as the
+.Fl b
+option.
+The
+.Fl k
+option overrides this option.
.It Fl t
Only print out statistics for file systems of the specified types.
More than one type may be specified in a comma separated list.
@@ -148,26 +161,53 @@ command can be used to find out the types of file systems
that are available on the system.
.It Fl T
Include file system type.
+.It Fl ,
+(Comma) Print sizes grouped and separated by thousands using the
+non-monetary separator returned by
+.Xr localeconv 3 ,
+typically a comma or period.
+If no locale is set, or the locale does not have a non-monetary separator, this
+option has no effect.
.El
.Sh ENVIRONMENT
.Bl -tag -width BLOCKSIZE
.It Ev BLOCKSIZE
-If the environment variable
-.Ev BLOCKSIZE
-is set, the block counts will be displayed in units of that size block.
+Specifies the units in which to report block counts.
+This uses
+.Xr getbsize 3 ,
+which allows units of bytes or numbers scaled with the letters
+.Em k
+(for multiples of 1024 bytes),
+.Em m
+(for multiples of 1048576 bytes) or
+.Em g
+(for gibibytes).
+The allowed range is 512 bytes to 1 GB.
+If the value is outside, it will be set to the appropriate limit.
.El
.Sh SEE ALSO
.Xr lsvfs 1 ,
-.Xr pstat 1 ,
.Xr quota 1 ,
-.Xr swapinfo 1 ,
.Xr fstatfs 2 ,
.Xr getfsstat 2 ,
.Xr statfs 2 ,
+.Xr getbsize 3 ,
.Xr getmntinfo 3 ,
+.Xr localeconv 3 ,
.Xr fstab 5 ,
.Xr mount 8 ,
-.Xr quot 8
+.Xr quot 8 .
+.Sh STANDARDS
+With the exception of most options,
+the
+.Nm
+utility conforms to
+.St -p1003.1-2004 ,
+which defines only the
+.Fl k , P
+and
+.Fl t
+options.
.Sh HISTORY
A
.Nm
@@ -180,3 +220,13 @@ flag is ignored if a file or file system is specified.
Also, if a mount
point is not accessible by the user, it is possible that the file system
information could be stale.
+.Pp
+The
+.Fl b
+and
+.Fl P
+options are identical.
+The former comes from the BSD tradition, and the latter is required
+for
+.St -p1003.1-2004
+conformity.
diff --git a/bin/df/df.c b/bin/df/df.c
index f865b8f1..77b7a40 100644
--- a/bin/df/df.c
+++ b/bin/df/df.c
@@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$");
#include <ufs/ufs/ufsmount.h>
#include <err.h>
#include <libutil.h>
+#include <locale.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@@ -95,6 +96,7 @@ imax(int a, int b)
}
static int aflag = 0, cflag, hflag, iflag, kflag, lflag = 0, nflag, Tflag;
+static int thousands;
static struct ufs_args mdev;
int
@@ -111,12 +113,12 @@ main(int argc, char *argv[])
int ch, rv;
fstype = "ufs";
-
+ (void)setlocale(LC_ALL, "");
memset(&totalbuf, 0, sizeof(totalbuf));
totalbuf.f_bsize = DEV_BSIZE;
strlcpy(totalbuf.f_mntfromname, "total", MNAMELEN);
vfslist = NULL;
- while ((ch = getopt(argc, argv, "abcgHhiklmnPt:T")) != -1)
+ while ((ch = getopt(argc, argv, "abcgHhiklmnPt:T,")) != -1)
switch (ch) {
case 'a':
aflag = 1;
@@ -180,6 +182,9 @@ main(int argc, char *argv[])
case 'T':
Tflag = 1;
break;
+ case ',':
+ thousands = 1;
+ break;
case '?':
default:
usage();
@@ -388,16 +393,11 @@ prthumanvalinode(int64_t bytes)
/*
* Convert statfs returned file system size into BLOCKSIZE units.
- * Attempts to avoid overflow for large file systems.
*/
static intmax_t
fsbtoblk(int64_t num, uint64_t fsbs, u_long bs)
{
-
- if (fsbs != 0 && fsbs < bs)
- return (num / (intmax_t)(bs / fsbs));
- else
- return (num * (intmax_t)(fsbs / bs));
+ return (num * (intmax_t) fsbs / (int64_t) bs);
}
/*
@@ -410,10 +410,18 @@ prtstat(struct statfs *sfsp, struct maxwidths *mwp)
static int headerlen, timesthrough = 0;
static const char *header;
int64_t used, availblks, inodes;
+ const char *format;
if (++timesthrough == 1) {
mwp->mntfrom = imax(mwp->mntfrom, (int)strlen("Filesystem"));
mwp->fstype = imax(mwp->fstype, (int)strlen("Type"));
+ if (thousands) { /* make space for commas */
+ mwp->total += (mwp->total - 1) / 3;
+ mwp->used += (mwp->used - 1) / 3;
+ mwp->avail += (mwp->avail - 1) / 3;
+ mwp->iused += (mwp->iused - 1) / 3;
+ mwp->ifree += (mwp->ifree - 1) / 3;
+ }
if (hflag) {
header = " Size";
mwp->total = mwp->used = mwp->avail =
@@ -428,7 +436,7 @@ prtstat(struct statfs *sfsp, struct maxwidths *mwp)
(void)printf("%-*s", mwp->mntfrom, "Filesystem");
if (Tflag)
(void)printf(" %-*s", mwp->fstype, "Type");
- (void)printf(" %-*s %*s %*s Capacity", mwp->total, header,
+ (void)printf(" %*s %*s %*s Capacity", mwp->total, header,
mwp->used, "Used", mwp->avail, "Avail");
if (iflag) {
mwp->iused = imax(hflag ? 0 : mwp->iused,
@@ -440,6 +448,12 @@ prtstat(struct statfs *sfsp, struct maxwidths *mwp)
}
(void)printf(" Mounted on\n");
}
+ /* Check for 0 block size. Can this happen? */
+ if (sfsp->f_bsize == 0) {
+ warnx ("File system %s does not have a block size, assuming 512.",
+ sfsp->f_mntonname);
+ sfsp->f_bsize = 512;
+ }
(void)printf("%-*s", mwp->mntfrom, sfsp->f_mntfromname);
if (Tflag)
(void)printf(" %-*s", mwp->fstype, sfsp->f_fstypename);
@@ -448,7 +462,11 @@ prtstat(struct statfs *sfsp, struct maxwidths *mwp)
if (hflag) {
prthuman(sfsp, used);
} else {
- (void)printf(" %*jd %*jd %*jd",
+ if (thousands)
+ format = " %*j'd %*j'd %*j'd";
+ else
+ format = " %*jd %*jd %*jd";
+ (void)printf(format,
mwp->total, fsbtoblk(sfsp->f_blocks,
sfsp->f_bsize, blocksize),
mwp->used, fsbtoblk(used, sfsp->f_bsize, blocksize),
@@ -465,7 +483,11 @@ prtstat(struct statfs *sfsp, struct maxwidths *mwp)
prthumanvalinode(used);
prthumanvalinode(sfsp->f_ffree);
} else {
- (void)printf(" %*jd %*jd", mwp->iused, (intmax_t)used,
+ if (thousands)
+ format = " %*j'd %*j'd";
+ else
+ format = " %*jd %*jd";
+ (void)printf(format, mwp->iused, (intmax_t)used,
mwp->ifree, (intmax_t)sfsp->f_ffree);
}
(void)printf(" %4.0f%% ", inodes == 0 ? 100.0 :
@@ -542,7 +564,8 @@ usage(void)
{
(void)fprintf(stderr,
-"usage: df [-b | -g | -H | -h | -k | -m | -P] [-acilnT] [-t type] [file | filesystem ...]\n");
+"usage: df [-b | -g | -H | -h | -k | -m | -P] [-acilnT] [-t type] [-,]\n"
+" [file | filesystem ...]\n");
exit(EX_USAGE);
}
diff --git a/bin/ln/ln.1 b/bin/ln/ln.1
index fcf97da..610f7bb 100644
--- a/bin/ln/ln.1
+++ b/bin/ln/ln.1
@@ -291,7 +291,7 @@ implementations.
.Pp
The
.Fl F
-option is
+option is a
.Fx
extension and should not be used in portable scripts.
.Sh SEE ALSO
diff --git a/bin/ls/cmp.c b/bin/ls/cmp.c
index 84fb038..a2e46ff 100644
--- a/bin/ls/cmp.c
+++ b/bin/ls/cmp.c
@@ -78,7 +78,10 @@ modcmp(const FTSENT *a, const FTSENT *b)
if (b->fts_statp->st_mtim.tv_nsec <
a->fts_statp->st_mtim.tv_nsec)
return (-1);
- return (strcoll(a->fts_name, b->fts_name));
+ if (f_samesort)
+ return (strcoll(b->fts_name, a->fts_name));
+ else
+ return (strcoll(a->fts_name, b->fts_name));
}
int
@@ -104,7 +107,10 @@ acccmp(const FTSENT *a, const FTSENT *b)
if (b->fts_statp->st_atim.tv_nsec <
a->fts_statp->st_atim.tv_nsec)
return (-1);
- return (strcoll(a->fts_name, b->fts_name));
+ if (f_samesort)
+ return (strcoll(b->fts_name, a->fts_name));
+ else
+ return (strcoll(a->fts_name, b->fts_name));
}
int
@@ -130,7 +136,10 @@ birthcmp(const FTSENT *a, const FTSENT *b)
if (b->fts_statp->st_birthtim.tv_nsec <
a->fts_statp->st_birthtim.tv_nsec)
return (-1);
- return (strcoll(a->fts_name, b->fts_name));
+ if (f_samesort)
+ return (strcoll(b->fts_name, a->fts_name));
+ else
+ return (strcoll(a->fts_name, b->fts_name));
}
int
@@ -156,7 +165,10 @@ statcmp(const FTSENT *a, const FTSENT *b)
if (b->fts_statp->st_ctim.tv_nsec <
a->fts_statp->st_ctim.tv_nsec)
return (-1);
- return (strcoll(a->fts_name, b->fts_name));
+ if (f_samesort)
+ return (strcoll(b->fts_name, a->fts_name));
+ else
+ return (strcoll(a->fts_name, b->fts_name));
}
int
diff --git a/bin/ls/extern.h b/bin/ls/extern.h
index f290fbb..90a20a8 100644
--- a/bin/ls/extern.h
+++ b/bin/ls/extern.h
@@ -55,12 +55,12 @@ int prn_octal(const char *);
int prn_printable(const char *);
#ifdef COLORLS
void parsecolors(const char *cs);
-void colorquit(int);
+void colorquit(int);
-extern char *ansi_fgcol;
-extern char *ansi_bgcol;
-extern char *ansi_coloff;
-extern char *attrs_off;
-extern char *enter_bold;
+extern char *ansi_fgcol;
+extern char *ansi_bgcol;
+extern char *ansi_coloff;
+extern char *attrs_off;
+extern char *enter_bold;
#endif
extern int termwidth;
diff --git a/bin/ls/ls.1 b/bin/ls/ls.1
index cc5ff48..aa4fc18 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 September 28, 2011
+.Dd November 8, 2012
.Dt LS 1
.Os
.Sh NAME
@@ -40,7 +40,7 @@
.Nd list directory contents
.Sh SYNOPSIS
.Nm
-.Op Fl ABCFGHILPRSTUWZabcdfghiklmnopqrstuwx1
+.Op Fl ABCFGHILPRSTUWZabcdfghiklmnopqrstuwxy1,
.Op Fl D Ar format
.Op Ar
.Sh DESCRIPTION
@@ -130,6 +130,8 @@ This option is equivalent to defining
.Ev CLICOLOR
in the environment.
(See below.)
+This functionality can be compiled out by removing the definition of
+.Ev COLORLS .
.It Fl H
Symbolic links on the command line are followed.
This option is assumed if
@@ -249,12 +251,35 @@ subsection below, except (if the long format is not also requested)
the directory totals are not output when the output is in a
single column, even if multi-column output is requested.
.It Fl t
-Sort by time modified (most recently modified
-first) before sorting the operands in lexicographical
-order.
+Sort by descending time modified (most recently modified first). If two files
+have the same modification timestamp, sort their names in ascending
+lexicographical order.
+The
+.Fl r
+option reverses both of these sort orders.
+.Pp
+Note that these sort orders are contradictory: the time sequence is in
+descending order, the lexicographical sort is in ascending order.
+This behavior is mandated by
+.St -p1003.2 .
+This feature can cause problems listing files stored with sequential names on
+FAT file systems, such as from digital cameras, where it is possible to have
+more than one image with the same timestamp.
+In such a case, the photos cannot be listed in the sequence in which
+they were taken.
+To ensure the same sort order for time and for lexicographical sorting, set the
+environment variable
+.Ev LS_SAMESORT
+or use the
+.Fl y
+option.
+This causes
+.Nm
+to reverse the lexicographal sort order when sorting files with the
+same modification timestamp.
.It Fl u
Use time of last access,
-instead of last modification
+instead of time of last modification
of the file for sorting
.Pq Fl t
or printing
@@ -268,6 +293,15 @@ The same as
.Fl C ,
except that the multi-column output is produced with entries sorted
across, rather than down, the columns.
+.It Fl y
+When the
+.Fl t
+option is set, sort the alphabetical output in the same order as the time output.
+This has the same effect as setting
+.Ev LS_SAMESORT .
+See the description of the
+.Fl t
+option for more details.
.It Fl 1
(The numeric digit
.Dq one . )
@@ -275,6 +309,15 @@ Force output to be
one entry per line.
This is the default when
output is not to a terminal.
+.It Fl ,
+(Comma) When the
+.Fl l
+option is set, print file sizes grouped and separated by thousands using the
+non-monetary separator returned by
+.Xr localeconv 3 ,
+typically a comma or period.
+If no locale is set, or the locale does not have a non-monetary separator, this
+option has no effect.
.El
.Pp
The
@@ -529,7 +572,7 @@ variable is defined.
.It Ev CLICOLOR_FORCE
Color sequences are normally disabled if the output is not directed to
a terminal.
-This can be overridden by setting this flag.
+This can be overridden by setting this variable.
The
.Ev TERM
variable still needs to reference a color capable terminal however
@@ -655,6 +698,14 @@ Not all columns have changeable widths.
The fields are,
in order: inode, block count, number of links, user name,
group name, flags, file size, file name.
+.It Ev LS_SAMESORT
+If this variable is set, the
+.Fl t
+option sorts the names of files with the same modification timestamp in the same
+sense as the time sort.
+See the description of the
+.Fl t
+option for more details.
.It Ev TERM
The
.Ev CLICOLOR
@@ -678,6 +729,7 @@ specification.
.Xr getfacl 1 ,
.Xr sort 1 ,
.Xr xterm 1 ,
+.Xr localeconv 3 ,
.Xr strftime 3 ,
.Xr strmode 3 ,
.Xr termcap 5 ,
@@ -716,3 +768,9 @@ option description might be a feature that was
based on the fact that single-column output
usually goes to something other than a terminal.
It is debatable whether this is a design bug.
+.Pp
+.St -p1003.2
+mandates opposite sort orders for files with the same timestamp when
+sorting with the
+.Fl t
+option.
diff --git a/bin/ls/ls.c b/bin/ls/ls.c
index b96d18b..be09035 100644
--- a/bin/ls/ls.c
+++ b/bin/ls/ls.c
@@ -109,10 +109,11 @@ int termwidth = 80; /* default terminal width */
int f_humanval; /* show human-readable file sizes */
int f_inode; /* print inode */
static int f_kblocks; /* print size in kilobytes */
+ int f_label; /* show MAC label */
static int f_listdir; /* list actual directory, not contents */
static int f_listdot; /* list files beginning with . */
-static int f_noautodot; /* do not automatically enable -A for root */
int f_longform; /* long listing format */
+static int f_noautodot; /* do not automatically enable -A for root */
static int f_nofollow; /* don't follow symbolic link arguments */
int f_nonprint; /* show unprintables as ? */
static int f_nosort; /* don't sort output */
@@ -122,19 +123,21 @@ static int f_numericonly; /* don't convert uid/gid to name */
int f_octal_escape; /* like f_octal but use C escapes if possible */
static int f_recursive; /* ls subdirectories also */
static int f_reversesort; /* reverse whatever sort is used */
- int f_sectime; /* print the real time for all files */
+ int f_samesort; /* sort time and name in same direction */
+ int f_sectime; /* print full time information */
static int f_singlecol; /* use single column output */
int f_size; /* list size in short listing */
+static int f_sizesort;
int f_slash; /* similar to f_type, but only for dirs */
int f_sortacross; /* sort across rows, not down columns */
int f_statustime; /* use time of last mode change */
static int f_stream; /* stream the output, separate with commas */
+ int f_thousands; /* show file sizes with thousands separators */
+ char *f_timeformat; /* user-specified time format */
static int f_timesort; /* sort by time vice name */
- char *f_timeformat; /* user-specified time format */
-static int f_sizesort;
int f_type; /* add type character for non-regular files */
static int f_whiteout; /* show whiteout entries */
- int f_label; /* show MAC label */
+
#ifdef COLORLS
int f_color; /* add type in color for non-regular files */
@@ -180,8 +183,10 @@ main(int argc, char *argv[])
}
fts_options = FTS_PHYSICAL;
- while ((ch = getopt(argc, argv,
- "1ABCD:FGHILPRSTUWZabcdfghiklmnopqrstuwx")) != -1) {
+ if (getenv("LS_SAMESORT"))
+ f_samesort = 1;
+ while ((ch = getopt(argc, argv,
+ "1ABCD:FGHILPRSTUWXZabcdfghiklmnopqrstuwxy,")) != -1) {
switch (ch) {
/*
* The -1, -C, -x and -l options all override each other so
@@ -192,17 +197,9 @@ main(int argc, char *argv[])
f_longform = 0;
f_stream = 0;
break;
- case 'B':
- f_nonprint = 0;
- f_octal = 1;
- f_octal_escape = 0;
- break;
case 'C':
f_sortacross = f_longform = f_singlecol = 0;
break;
- case 'D':
- f_timeformat = optarg;
- break;
case 'l':
f_longform = 1;
f_singlecol = 0;
@@ -229,16 +226,46 @@ main(int argc, char *argv[])
f_accesstime = 0;
f_statustime = 0;
break;
+ case 'a':
+ fts_options |= FTS_SEEDOT;
+ /* FALLTHROUGH */
+ case 'A':
+ f_listdot = 1;
+ break;
+ /* The -t and -S options override each other. */
+ case 'S':
+ f_sizesort = 1;
+ f_timesort = 0;
+ break;
+ case 't':
+ f_timesort = 1;
+ f_sizesort = 0;
+ break;
+ /* Other flags. Please keep alphabetic. */
+ case ',':
+ f_thousands = 1;
+ break;
+ case 'B':
+ f_nonprint = 0;
+ f_octal = 1;
+ f_octal_escape = 0;
+ break;
+ case 'D':
+ f_timeformat = optarg;
+ break;
case 'F':
f_type = 1;
f_slash = 0;
break;
+ case 'G':
+ setenv("CLICOLOR", "", 1);
+ break;
case 'H':
fts_options |= FTS_COMFOLLOW;
f_nofollow = 0;
break;
- case 'G':
- setenv("CLICOLOR", "", 1);
+ case 'I':
+ f_noautodot = 1;
break;
case 'L':
fts_options &= ~FTS_PHYSICAL;
@@ -254,14 +281,19 @@ main(int argc, char *argv[])
case 'R':
f_recursive = 1;
break;
- case 'a':
- fts_options |= FTS_SEEDOT;
- /* FALLTHROUGH */
- case 'A':
- f_listdot = 1;
+ case 'T':
+ f_sectime = 1;
break;
- case 'I':
- f_noautodot = 1;
+ case 'W':
+ f_whiteout = 1;
+ break;
+ case 'Z':
+ f_label = 1;
+ break;
+ case 'b':
+ f_nonprint = 0;
+ f_octal = 0;
+ f_octal_escape = 1;
break;
/* The -d option turns off the -R option. */
case 'd':
@@ -309,33 +341,13 @@ main(int argc, char *argv[])
case 's':
f_size = 1;
break;
- case 'T':
- f_sectime = 1;
- break;
- /* The -t and -S options override each other. */
- case 't':
- f_timesort = 1;
- f_sizesort = 0;
- break;
- case 'S':
- f_sizesort = 1;
- f_timesort = 0;
- break;
- case 'W':
- f_whiteout = 1;
- break;
- case 'b':
- f_nonprint = 0;
- f_octal = 0;
- f_octal_escape = 1;
- break;
case 'w':
f_nonprint = 0;
f_octal = 0;
f_octal_escape = 0;
break;
- case 'Z':
- f_label = 1;
+ case 'y':
+ f_samesort = 1;
break;
default:
case '?':
@@ -849,6 +861,8 @@ label_out:
d.s_size = sizelen;
d.s_user = maxuser;
}
+ if (f_thousands) /* make space for commas */
+ d.s_size += (d.s_size - 1) / 3;
printfcn(&d);
output = 1;
diff --git a/bin/ls/ls.h b/bin/ls/ls.h
index ee2a7a5..1a45eb4 100644
--- a/bin/ls/ls.h
+++ b/bin/ls/ls.h
@@ -49,12 +49,14 @@ extern int f_longform; /* long listing format */
extern int f_octal; /* print unprintables in octal */
extern int f_octal_escape; /* like f_octal but use C escapes if possible */
extern int f_nonprint; /* show unprintables as ? */
+extern int f_samesort; /* sort time and name in same direction */
extern int f_sectime; /* print the real time for all files */
extern int f_size; /* list size in short listing */
extern int f_slash; /* append a '/' if the file is a directory */
extern int f_sortacross; /* sort across rows, not down columns */
extern int f_statustime; /* use time of last mode change */
-extern char *f_timeformat; /* user-specified time format */
+extern int f_thousands; /* show file sizes with thousands separators */
+extern char *f_timeformat; /* user-specified time format */
extern int f_notabs; /* don't use tab-separated multi-col output */
extern int f_type; /* add type character for non-regular files */
#ifdef COLORLS
diff --git a/bin/ls/print.c b/bin/ls/print.c
index 5a0fc86..930d6ea 100644
--- a/bin/ls/print.c
+++ b/bin/ls/print.c
@@ -606,6 +606,10 @@ printsize(size_t width, off_t bytes)
humanize_number(buf, sizeof(buf), (int64_t)bytes, "",
HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
(void)printf("%*s ", (u_int)width, buf);
+ } else if (f_thousands) { /* with commas */
+ /* This format assignment needed to work round gcc bug. */
+ const char *format = "%*j'd ";
+ (void)printf(format, (u_int)width, bytes);
} else
(void)printf("%*jd ", (u_int)width, bytes);
}
diff --git a/bin/ls/util.c b/bin/ls/util.c
index ecb1732..f8466cd 100644
--- a/bin/ls/util.c
+++ b/bin/ls/util.c
@@ -132,7 +132,7 @@ prn_printable(const char *s)
* to fix this as an efficient fix would involve a lookup table. Same goes
* for the rather inelegant code in prn_octal.
*
- * DES 1998/04/23
+ * DES 1998/04/23
*/
size_t
@@ -175,7 +175,7 @@ prn_octal(const char *s)
size_t clen;
unsigned char ch;
int goodchar, i, len, prtlen;
-
+
memset(&mbs, 0, sizeof(mbs));
len = 0;
while ((clen = mbrtowc(&wc, s, MB_LEN_MAX, &mbs)) != 0) {
@@ -184,7 +184,10 @@ prn_octal(const char *s)
for (i = 0; i < (int)clen; i++)
putchar((unsigned char)s[i]);
len += wcwidth(wc);
- } else if (goodchar && f_octal_escape && wc >= 0 &&
+ } else if (goodchar && f_octal_escape &&
+#if WCHAR_MIN < 0
+ wc >= 0 &&
+#endif
wc <= (wchar_t)UCHAR_MAX &&
(p = strchr(esc, (char)wc)) != NULL) {
putchar('\\');
@@ -200,9 +203,9 @@ prn_octal(const char *s)
for (i = 0; i < prtlen; i++) {
ch = (unsigned char)s[i];
putchar('\\');
- putchar('0' + (ch >> 6));
- putchar('0' + ((ch >> 3) & 7));
- putchar('0' + (ch & 7));
+ putchar('0' + (ch >> 6));
+ putchar('0' + ((ch >> 3) & 7));
+ putchar('0' + (ch & 7));
len += 4;
}
}
@@ -222,9 +225,9 @@ usage(void)
{
(void)fprintf(stderr,
#ifdef COLORLS
- "usage: ls [-ABCFGHILPRSTUWZabcdfghiklmnopqrstuwx1] [-D format]"
+ "usage: ls [-ABCFGHILPRSTUWZabcdfghiklmnopqrstuwxy1,] [-D format]"
#else
- "usage: ls [-ABCFHILPRSTUWZabcdfghiklmnopqrstuwx1] [-D format]"
+ "usage: ls [-ABCFHILPRSTUWZabcdfghiklmnopqrstuwxy1,] [-D format]"
#endif
" [file ...]\n");
exit(1);
diff --git a/bin/mv/mv.c b/bin/mv/mv.c
index d33b28d..5147a2db 100644
--- a/bin/mv/mv.c
+++ b/bin/mv/mv.c
@@ -199,7 +199,7 @@ do_move(const char *from, const char *to)
} else if (iflg) {
(void)fprintf(stderr, "overwrite %s? %s", to, YESNO);
ask = 1;
- } else if (access(to, W_OK) && !stat(to, &sb)) {
+ } else if (access(to, W_OK) && !stat(to, &sb) && isatty(STDIN_FILENO)) {
strmode(sb.st_mode, modep);
(void)fprintf(stderr, "override %s%s%s/%s for %s? %s",
modep + 1, modep[9] == ' ' ? "" : " ",
diff --git a/bin/ps/extern.h b/bin/ps/extern.h
index 930b85b..eb9b2cf 100644
--- a/bin/ps/extern.h
+++ b/bin/ps/extern.h
@@ -51,7 +51,7 @@ char *elapsed(KINFO *, VARENT *);
char *elapseds(KINFO *, VARENT *);
char *emulname(KINFO *, VARENT *);
VARENT *find_varentry(VAR *);
-const char *fmt_argv(char **, char *, size_t);
+const char *fmt_argv(char **, char *, char *, size_t);
double getpcpu(const KINFO *);
char *kvar(KINFO *, VARENT *);
char *label(KINFO *, VARENT *);
diff --git a/bin/ps/fmt.c b/bin/ps/fmt.c
index 1e9fed8..4db6b8d 100644
--- a/bin/ps/fmt.c
+++ b/bin/ps/fmt.c
@@ -105,7 +105,7 @@ cmdpart(char *arg0)
}
const char *
-fmt_argv(char **argv, char *cmd, size_t maxlen)
+fmt_argv(char **argv, char *cmd, char *thread, size_t maxlen)
{
size_t len;
char *ap, *cp;
@@ -122,9 +122,14 @@ fmt_argv(char **argv, char *cmd, size_t maxlen)
cp = malloc(len);
if (cp == NULL)
errx(1, "malloc failed");
- if (ap == NULL)
- sprintf(cp, "[%.*s]", (int)maxlen, cmd);
- else if (strncmp(cmdpart(argv[0]), cmd, maxlen) != 0)
+ if (ap == NULL) {
+ if (thread != NULL) {
+ asprintf(&ap, "%s/%s", cmd, thread);
+ sprintf(cp, "[%.*s]", (int)maxlen, ap);
+ free(ap);
+ } else
+ sprintf(cp, "[%.*s]", (int)maxlen, cmd);
+ } else if (strncmp(cmdpart(argv[0]), cmd, maxlen) != 0)
sprintf(cp, "%s (%.*s)", ap, (int)maxlen, cmd);
else
strcpy(cp, ap);
diff --git a/bin/ps/ps.1 b/bin/ps/ps.1
index 21e8eaf..7f69137 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 September 18, 2012
+.Dd February 7, 2013
.Dt PS 1
.Os
.Sh NAME
@@ -323,6 +323,7 @@ the include file
.It Dv "P_INMEM" Ta No "0x10000000" Ta "Loaded into memory"
.It Dv "P_SWAPPINGOUT" Ta No "0x20000000" Ta "Process is being swapped out"
.It Dv "P_SWAPPINGIN" Ta No "0x40000000" Ta "Process is being swapped in"
+.It Dv "P_PPTRACE" Ta No "0x80000000" Ta "Vforked child issued ptrace(PT_TRACEME)"
.El
.It Cm label
The MAC label of the process.
diff --git a/bin/ps/ps.c b/bin/ps/ps.c
index ebabc19..7099cc0 100644
--- a/bin/ps/ps.c
+++ b/bin/ps/ps.c
@@ -109,6 +109,7 @@ static int needcomm; /* -o "command" */
static int needenv; /* -e */
static int needuser; /* -o "user" */
static int optfatal; /* Fatal error parsing some list-option. */
+static int pid_max; /* kern.max_pid */
static enum sort { DEFAULT, SORTMEM, SORTCPU } sortby = DEFAULT;
@@ -140,7 +141,7 @@ static void format_output(KINFO *);
static void *expand_list(struct listinfo *);
static const char *
fmt(char **(*)(kvm_t *, const struct kinfo_proc *, int),
- KINFO *, char *, int);
+ KINFO *, char *, char *, int);
static void free_list(struct listinfo *);
static void init_list(struct listinfo *, addelem_rtn, int, const char *);
static char *kludge_oldps_options(const char *, char *, const char *);
@@ -148,6 +149,7 @@ static int pscomp(const void *, const void *);
static void saveuser(KINFO *);
static void scanvars(void);
static void sizevars(void);
+static void pidmax_init(void);
static void usage(void);
static char dfmt[] = "pid,tt,state,time,command";
@@ -200,6 +202,8 @@ main(int argc, char *argv[])
if (argc > 1)
argv[1] = kludge_oldps_options(PS_ARGS, argv[1], argv[2]);
+ pidmax_init();
+
all = descendancy = _fmt = nselectors = optfatal = 0;
prtheader = showthreads = wflag = xkeep_implied = 0;
xkeep = -1; /* Neither -x nor -X. */
@@ -722,7 +726,6 @@ addelem_gid(struct listinfo *inf, const char *elem)
return (1);
}
-#define BSD_PID_MAX 99999 /* Copy of PID_MAX from sys/proc.h. */
static int
addelem_pid(struct listinfo *inf, const char *elem)
{
@@ -740,7 +743,7 @@ addelem_pid(struct listinfo *inf, const char *elem)
if (*endp != '\0' || tempid < 0 || elem == endp) {
warnx("Invalid %s: %s", inf->lname, elem);
errno = ERANGE;
- } else if (errno != 0 || tempid > BSD_PID_MAX) {
+ } else if (errno != 0 || tempid > pid_max) {
warnx("%s too large: %s", inf->lname, elem);
errno = ERANGE;
}
@@ -753,7 +756,6 @@ addelem_pid(struct listinfo *inf, const char *elem)
inf->l.pids[(inf->count)++] = tempid;
return (1);
}
-#undef BSD_PID_MAX
/*-
* The user can specify a device via one of three formats:
@@ -1161,11 +1163,12 @@ sizevars(void)
static const char *
fmt(char **(*fn)(kvm_t *, const struct kinfo_proc *, int), KINFO *ki,
- char *comm, int maxlen)
+ char *comm, char *thread, int maxlen)
{
const char *s;
- s = fmt_argv((*fn)(kd, ki->ki_p, termwidth), comm, maxlen);
+ s = fmt_argv((*fn)(kd, ki->ki_p, termwidth), comm,
+ showthreads && ki->ki_p->ki_numthreads > 1 ? thread : NULL, maxlen);
return (s);
}
@@ -1193,7 +1196,7 @@ saveuser(KINFO *ki)
ki->ki_args = strdup("<defunct>");
else if (UREADOK(ki) || (ki->ki_p->ki_args != NULL))
ki->ki_args = strdup(fmt(kvm_getargv, ki,
- ki->ki_p->ki_comm, MAXCOMLEN));
+ ki->ki_p->ki_comm, ki->ki_p->ki_tdname, MAXCOMLEN));
else
asprintf(&ki->ki_args, "(%s)", ki->ki_p->ki_comm);
if (ki->ki_args == NULL)
@@ -1204,7 +1207,7 @@ saveuser(KINFO *ki)
if (needenv) {
if (UREADOK(ki))
ki->ki_env = strdup(fmt(kvm_getenvv, ki,
- (char *)NULL, 0));
+ (char *)NULL, (char *)NULL, 0));
else
ki->ki_env = strdup("()");
if (ki->ki_env == NULL)
@@ -1352,6 +1355,18 @@ kludge_oldps_options(const char *optlist, char *origval, const char *nextarg)
}
static void
+pidmax_init(void)
+{
+ size_t intsize;
+
+ intsize = sizeof(pid_max);
+ if (sysctlbyname("kern.pid_max", &pid_max, &intsize, NULL, 0) < 0) {
+ warn("unable to read kern.pid_max");
+ pid_max = 99999;
+ }
+}
+
+static void
usage(void)
{
#define SINGLE_OPTS "[-aCcde" OPT_LAZY_f "HhjlmrSTuvwXxZ]"
diff --git a/bin/pwait/pwait.c b/bin/pwait/pwait.c
index 26cf1bd..6851fad 100644
--- a/bin/pwait/pwait.c
+++ b/bin/pwait/pwait.c
@@ -141,5 +141,5 @@ main(int argc, char *argv[])
nleft -= n;
}
- return 0;
+ exit(EX_OK);
}
diff --git a/bin/sh/TOUR b/bin/sh/TOUR
index 4b61bdf..13438b5 100644
--- a/bin/sh/TOUR
+++ b/bin/sh/TOUR
@@ -33,10 +33,6 @@ programs is:
There are undoubtedly too many of these. Mkinit searches all the
C source files for entries looking like:
- INIT {
- x = 1; /* executed during initialization */
- }
-
RESET {
x = 2; /* executed when the shell does a longjmp
back to the main command loop */
diff --git a/bin/sh/alias.c b/bin/sh/alias.c
index fb0e922..da995bb 100644
--- a/bin/sh/alias.c
+++ b/bin/sh/alias.c
@@ -68,7 +68,18 @@ setalias(const char *name, const char *val)
if (equal(name, ap->name)) {
INTOFF;
ckfree(ap->val);
+ /* See HACK below. */
+#ifdef notyet
ap->val = savestr(val);
+#else
+ {
+ size_t len = strlen(val);
+ ap->val = ckmalloc(len + 2);
+ memcpy(ap->val, val, len);
+ ap->val[len] = ' ';
+ ap->val[len+1] = '\0';
+ }
+#endif
INTON;
return;
}
diff --git a/bin/sh/eval.c b/bin/sh/eval.c
index 8973f69..66ae40e 100644
--- a/bin/sh/eval.c
+++ b/bin/sh/eval.c
@@ -92,6 +92,7 @@ static void evalfor(union node *, int);
static union node *evalcase(union node *);
static void evalsubshell(union node *, int);
static void evalredir(union node *, int);
+static void exphere(union node *, struct arglist *);
static void expredir(union node *);
static void evalpipe(union node *);
static int is_valid_fast_cmdsubst(union node *n);
@@ -193,7 +194,9 @@ evaltree(union node *n, int flags)
{
int do_etest;
union node *next;
+ struct stackmark smark;
+ setstackmark(&smark);
do_etest = 0;
if (n == NULL) {
TRACE(("evaltree(NULL) called\n"));
@@ -292,8 +295,10 @@ evaltree(union node *n, int flags)
break;
}
n = next;
+ popstackmark(&smark);
} while (n != NULL);
out:
+ popstackmark(&smark);
if (pendingsigs)
dotrap();
if (eflag && exitstatus != 0 && do_etest)
@@ -347,10 +352,8 @@ evalfor(union node *n, int flags)
struct arglist arglist;
union node *argp;
struct strlist *sp;
- struct stackmark smark;
int status;
- setstackmark(&smark);
arglist.lastp = &arglist.list;
for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
oexitstatus = exitstatus;
@@ -375,7 +378,6 @@ evalfor(union node *n, int flags)
}
}
loopnest--;
- popstackmark(&smark);
exitstatus = status;
}
@@ -392,16 +394,13 @@ evalcase(union node *n)
union node *cp;
union node *patp;
struct arglist arglist;
- struct stackmark smark;
- setstackmark(&smark);
arglist.lastp = &arglist.list;
oexitstatus = exitstatus;
expandarg(n->ncase.expr, &arglist, EXP_TILDE);
for (cp = n->ncase.cases ; cp ; cp = cp->nclist.next) {
for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
if (casematch(patp, arglist.list->text)) {
- popstackmark(&smark);
while (cp->nclist.next &&
cp->type == NCLISTFALLTHRU &&
cp->nclist.body == NULL)
@@ -415,7 +414,6 @@ evalcase(union node *n)
}
}
}
- popstackmark(&smark);
exitstatus = 0;
return (NULL);
}
@@ -491,6 +489,37 @@ evalredir(union node *n, int flags)
}
+static void
+exphere(union node *redir, struct arglist *fn)
+{
+ struct jmploc jmploc;
+ struct jmploc *savehandler;
+ struct localvar *savelocalvars;
+ int need_longjmp = 0;
+
+ redir->nhere.expdoc = nullstr;
+ savelocalvars = localvars;
+ localvars = NULL;
+ forcelocal++;
+ savehandler = handler;
+ if (setjmp(jmploc.loc))
+ need_longjmp = exception != EXERROR && exception != EXEXEC;
+ else {
+ handler = &jmploc;
+ expandarg(redir->nhere.doc, fn, 0);
+ redir->nhere.expdoc = fn->list->text;
+ INTOFF;
+ }
+ handler = savehandler;
+ forcelocal--;
+ poplocalvars();
+ localvars = savelocalvars;
+ if (need_longjmp)
+ longjmp(handler->loc, 1);
+ INTON;
+}
+
+
/*
* Compute the names of the files in a redirection list.
*/
@@ -519,6 +548,9 @@ expredir(union node *n)
fixredir(redir, fn.list->text, 1);
}
break;
+ case NXHERE:
+ exphere(redir, &fn);
+ break;
}
}
}
@@ -610,7 +642,7 @@ evalbackcmd(union node *n, struct backcmd *result)
{
int pip[2];
struct job *jp;
- struct stackmark smark; /* unnecessary */
+ struct stackmark smark;
struct jmploc jmploc;
struct jmploc *savehandler;
struct localvar *savelocalvars;
@@ -624,8 +656,8 @@ evalbackcmd(union node *n, struct backcmd *result)
exitstatus = 0;
goto out;
}
+ exitstatus = oexitstatus;
if (is_valid_fast_cmdsubst(n)) {
- exitstatus = oexitstatus;
savelocalvars = localvars;
localvars = NULL;
forcelocal++;
@@ -649,7 +681,6 @@ evalbackcmd(union node *n, struct backcmd *result)
poplocalvars();
localvars = savelocalvars;
} else {
- exitstatus = 0;
if (pipe(pip) < 0)
error("Pipe call failed: %s", strerror(errno));
jp = makejob(n, 1);
@@ -752,7 +783,6 @@ safe_builtin(int idx, int argc, char **argv)
static void
evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
{
- struct stackmark smark;
union node *argp;
struct arglist arglist;
struct arglist varlist;
@@ -779,7 +809,6 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
/* First expand the arguments. */
TRACE(("evalcommand(%p, %d) called\n", (void *)cmd, flags));
- setstackmark(&smark);
arglist.lastp = &arglist.list;
varlist.lastp = &varlist.list;
varflag = 1;
@@ -1070,6 +1099,7 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
}
handler = &jmploc;
redirect(cmd->ncmd.redirect, mode);
+ outclearerror(out1);
/*
* If there is no command word, redirection errors should
* not be fatal but assignment errors should.
@@ -1085,6 +1115,11 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
builtin_flags = flags;
exitstatus = (*builtinfunc[cmdentry.u.index])(argc, argv);
flushall();
+ if (outiserror(out1)) {
+ warning("write error on stdout");
+ if (exitstatus == 0 || exitstatus == 1)
+ exitstatus = 2;
+ }
cmddone:
if (argc > 0)
bltinunsetlocale();
@@ -1144,7 +1179,6 @@ out:
setvar("_", lastarg, 0);
if (do_clearcmdentry)
clearcmdentry();
- popstackmark(&smark);
}
diff --git a/bin/sh/exec.c b/bin/sh/exec.c
index cd49589..7a6dbae 100644
--- a/bin/sh/exec.c
+++ b/bin/sh/exec.c
@@ -78,7 +78,6 @@ __FBSDID("$FreeBSD$");
#define CMDTABLESIZE 31 /* should be prime */
-#define ARB 1 /* actual size determined at run time */
@@ -86,13 +85,13 @@ struct tblentry {
struct tblentry *next; /* next entry in hash chain */
union param param; /* definition of builtin function */
int special; /* flag for special builtin commands */
- short cmdtype; /* index identifying command */
- char rehash; /* if set, cd done since entry created */
- char cmdname[ARB]; /* name of command */
+ signed char cmdtype; /* index identifying command */
+ char cmdname[]; /* name of command */
};
static struct tblentry *cmdtable[CMDTABLESIZE];
+static int cmdtable_cd = 0; /* cmdtable contains cd-dependent entries */
int exerrno = 0; /* Last exec error */
@@ -306,8 +305,6 @@ printentry(struct tblentry *cmdp, int verbose)
error("internal error: cmdtype %d", cmdp->cmdtype);
#endif
}
- if (cmdp->rehash)
- out1c('*');
out1c('\n');
}
@@ -324,12 +321,12 @@ find_command(const char *name, struct cmdentry *entry, int act,
{
struct tblentry *cmdp, loc_cmd;
int idx;
- int prev;
char *fullname;
struct stat statb;
int e;
int i;
int spec;
+ int cd;
/* If name contains a slash, don't use the hash table */
if (strchr(name, '/') != NULL) {
@@ -338,8 +335,10 @@ find_command(const char *name, struct cmdentry *entry, int act,
return;
}
+ cd = 0;
+
/* If name is in the table, and not invalidated by cd, we're done */
- if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->rehash == 0) {
+ if ((cmdp = cmdlookup(name, 0)) != NULL) {
if (cmdp->cmdtype == CMDFUNCTION && act & DO_NOFUNC)
cmdp = NULL;
else
@@ -360,13 +359,6 @@ find_command(const char *name, struct cmdentry *entry, int act,
}
/* We have to search path. */
- prev = -1; /* where to start */
- if (cmdp) { /* doing a rehash */
- if (cmdp->cmdtype == CMDBUILTIN)
- prev = -1;
- else
- prev = cmdp->param.index;
- }
e = ENOENT;
idx = -1;
@@ -381,13 +373,8 @@ loop:
goto loop; /* ignore unimplemented options */
}
}
- /* if rehash, don't redo absolute path names */
- if (fullname[0] == '/' && idx <= prev) {
- if (idx < prev)
- goto loop;
- TRACE(("searchexec \"%s\": no change\n", name));
- goto success;
- }
+ if (fullname[0] != '/')
+ cd = 1;
if (stat(fullname, &statb) < 0) {
if (errno != ENOENT && errno != ENOTDIR)
e = errno;
@@ -427,9 +414,6 @@ loop:
goto success;
}
- /* We failed. If there was an entry for this command, delete it */
- if (cmdp && cmdp->cmdtype != CMDFUNCTION)
- delete_cmd_entry();
if (act & DO_ERR) {
if (e == ENOENT || e == ENOTDIR)
outfmt(out2, "%s: not found\n", name);
@@ -441,7 +425,8 @@ loop:
return;
success:
- cmdp->rehash = 0;
+ if (cd)
+ cmdtable_cd = 1;
entry->cmdtype = cmdp->cmdtype;
entry->u = cmdp->param;
entry->special = cmdp->special;
@@ -470,22 +455,15 @@ find_builtin(const char *name, int *special)
/*
- * Called when a cd is done. Marks all commands so the next time they
- * are executed they will be rehashed.
+ * Called when a cd is done. If any entry in cmdtable depends on the current
+ * directory, simply clear cmdtable completely.
*/
void
hashcd(void)
{
- struct tblentry **pp;
- struct tblentry *cmdp;
-
- for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
- for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
- if (cmdp->cmdtype == CMDNORMAL)
- cmdp->rehash = 1;
- }
- }
+ if (cmdtable_cd)
+ clearcmdentry();
}
@@ -527,6 +505,7 @@ clearcmdentry(void)
}
}
}
+ cmdtable_cd = 0;
INTON;
}
@@ -563,11 +542,10 @@ cmdlookup(const char *name, int add)
}
if (add && cmdp == NULL) {
INTOFF;
- cmdp = *pp = ckmalloc(sizeof (struct tblentry) - ARB
+ cmdp = *pp = ckmalloc(sizeof (struct tblentry)
+ strlen(name) + 1);
cmdp->next = NULL;
cmdp->cmdtype = CMDUNKNOWN;
- cmdp->rehash = 0;
strcpy(cmdp->cmdname, name);
INTON;
}
diff --git a/bin/sh/expand.c b/bin/sh/expand.c
index d43cc35..107f798 100644
--- a/bin/sh/expand.c
+++ b/bin/sh/expand.c
@@ -127,19 +127,6 @@ collate_range_cmp(wchar_t c1, wchar_t c2)
return (wcscoll(s1, s2));
}
-/*
- * Expand shell variables and backquotes inside a here document.
- * union node *arg the document
- * int fd; where to write the expanded version
- */
-
-void
-expandhere(union node *arg, int fd)
-{
- expandarg(arg, (struct arglist *)NULL, 0);
- xwrite(fd, stackblock(), expdest - stackblock());
-}
-
static char *
stputs_quotes(const char *data, const char *syntax, char *p)
{
diff --git a/bin/sh/expand.h b/bin/sh/expand.h
index 8114e2b..8d44321 100644
--- a/bin/sh/expand.h
+++ b/bin/sh/expand.h
@@ -57,7 +57,6 @@ struct arglist {
union node;
-void expandhere(union node *, int);
void expandarg(union node *, struct arglist *, int);
void expari(int);
void rmescapes(char *);
diff --git a/bin/sh/init.h b/bin/sh/init.h
index dd0c4a8..384bb69 100644
--- a/bin/sh/init.h
+++ b/bin/sh/init.h
@@ -33,5 +33,4 @@
* $FreeBSD$
*/
-void init(void);
void reset(void);
diff --git a/bin/sh/input.c b/bin/sh/input.c
index 12f285f..84580ad 100644
--- a/bin/sh/input.c
+++ b/bin/sh/input.c
@@ -64,7 +64,6 @@ __FBSDID("$FreeBSD$");
#define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
-MKINIT
struct strpush {
struct strpush *prev; /* preceding string on stack */
char *prevstring;
@@ -78,7 +77,6 @@ struct strpush {
* contains information about the current file being read.
*/
-MKINIT
struct parsefile {
struct parsefile *prev; /* preceding file on stack */
int linno; /* current line */
@@ -96,10 +94,12 @@ 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 */
-MKINIT struct parsefile basepf; /* top level input file */
-char basebuf[BUFSIZ + 1]; /* buffer for top level input file */
+static char basebuf[BUFSIZ + 1];/* buffer for top level input file */
+static struct parsefile basepf = { /* top level input file */
+ .nextc = basebuf,
+ .buf = basebuf
+};
static struct parsefile *parsefile = &basepf; /* current input file */
-int init_editline = 0; /* editline library initialized? */
int whichprompt; /* 1 == PS1, 2 == PS2 */
EditLine *el; /* cookie for editline package */
@@ -112,12 +112,6 @@ static void popstring(void);
INCLUDE "input.h"
INCLUDE "error.h"
-MKINIT char basebuf[];
-
-INIT {
- basepf.nextc = basepf.buf = basebuf;
-}
-
RESET {
popallfiles();
parselleft = parsenleft = 0; /* clear input buffer */
@@ -350,7 +344,7 @@ pungetc(void)
* We handle aliases this way.
*/
void
-pushstring(char *s, int len, void *ap)
+pushstring(char *s, int len, struct alias *ap)
{
struct strpush *sp;
@@ -365,9 +359,9 @@ pushstring(char *s, int len, void *ap)
sp->prevstring = parsenextc;
sp->prevnleft = parsenleft;
sp->prevlleft = parselleft;
- sp->ap = (struct alias *)ap;
+ sp->ap = ap;
if (ap)
- ((struct alias *)ap)->flag |= ALIASINUSE;
+ ap->flag |= ALIASINUSE;
parsenextc = s;
parsenleft = len;
INTON;
diff --git a/bin/sh/input.h b/bin/sh/input.h
index 92aba45..c8802f9 100644
--- a/bin/sh/input.h
+++ b/bin/sh/input.h
@@ -43,8 +43,8 @@
extern int plinno;
extern int parsenleft; /* number of characters left in input buffer */
extern char *parsenextc; /* next character in input buffer */
-extern int init_editline; /* 0 == not setup, 1 == OK, -1 == failed */
+struct alias;
struct parsefile;
char *pfgets(char *, int);
@@ -52,7 +52,7 @@ int pgetc(void);
int preadbuffer(void);
int preadateof(void);
void pungetc(void);
-void pushstring(char *, int, void *);
+void pushstring(char *, int, struct alias *);
void setinputfile(const char *, int);
void setinputfd(int, int);
void setinputstring(char *, int);
diff --git a/bin/sh/jobs.c b/bin/sh/jobs.c
index 05e2e88..c86394f 100644
--- a/bin/sh/jobs.c
+++ b/bin/sh/jobs.c
@@ -298,6 +298,7 @@ showjob(struct job *jp, int mode)
{
char s[64];
char statestr[64];
+ const char *sigstr;
struct procstat *ps;
struct job *j;
int col, curr, i, jobno, prev, procno;
@@ -324,8 +325,9 @@ showjob(struct job *jp, int mode)
i = WSTOPSIG(ps->status);
else
i = -1;
- if (i > 0 && i < sys_nsig && sys_siglist[i])
- strcpy(statestr, sys_siglist[i]);
+ sigstr = strsignal(i);
+ if (sigstr != NULL)
+ strcpy(statestr, sigstr);
else
strcpy(statestr, "Suspended");
#endif
@@ -337,10 +339,11 @@ showjob(struct job *jp, int mode)
WEXITSTATUS(ps->status));
} else {
i = WTERMSIG(ps->status);
- if (i > 0 && i < sys_nsig && sys_siglist[i])
- strcpy(statestr, sys_siglist[i]);
+ sigstr = strsignal(i);
+ if (sigstr != NULL)
+ strcpy(statestr, sigstr);
else
- fmtstr(statestr, 64, "Signal %d", i);
+ strcpy(statestr, "Unknown signal");
if (WCOREDUMP(ps->status))
strcat(statestr, " (core dumped)");
}
@@ -1019,6 +1022,7 @@ dowait(int mode, struct job *job)
struct procstat *sp;
struct job *jp;
struct job *thisjob;
+ const char *sigstr;
int done;
int stopped;
int sig;
@@ -1026,7 +1030,7 @@ dowait(int mode, struct job *job)
int wflags;
int restore_sigchld;
- TRACE(("dowait(%d) called\n", block));
+ TRACE(("dowait(%d, %p) called\n", mode, job));
restore_sigchld = 0;
if ((mode & DOWAIT_SIG) != 0) {
sigfillset(&mask);
@@ -1129,10 +1133,11 @@ dowait(int mode, struct job *job)
coredump = WCOREDUMP(sp->status);
}
if (sig > 0 && sig != SIGINT && sig != SIGPIPE) {
- if (sig < sys_nsig && sys_siglist[sig])
- out2str(sys_siglist[sig]);
+ sigstr = strsignal(sig);
+ if (sigstr != NULL)
+ out2str(sigstr);
else
- outfmt(out2, "Signal %d", sig);
+ out2str("Unknown signal");
if (coredump)
out2str(" (core dumped)");
out2c('\n');
@@ -1293,6 +1298,10 @@ until:
cmdputs(n->narg.text);
cmdputs("() ...");
break;
+ case NNOT:
+ cmdputs("! ");
+ cmdtxt(n->nnot.com);
+ break;
case NCMD:
for (np = n->ncmd.args ; np ; np = np->narg.next) {
cmdtxt(np);
diff --git a/bin/sh/main.c b/bin/sh/main.c
index b93f04e..66e1335 100644
--- a/bin/sh/main.c
+++ b/bin/sh/main.c
@@ -139,7 +139,7 @@ main(int argc, char *argv[])
#endif
rootpid = getpid();
rootshell = 1;
- init();
+ initvar();
setstackmark(&smark);
setstackmark(&smark2);
procargs(argc, argv);
diff --git a/bin/sh/miscbltin.c b/bin/sh/miscbltin.c
index f602177..b81cc82 100644
--- a/bin/sh/miscbltin.c
+++ b/bin/sh/miscbltin.c
@@ -47,7 +47,6 @@ __FBSDID("$FreeBSD$");
#include <sys/time.h>
#include <sys/resource.h>
#include <unistd.h>
-#include <ctype.h>
#include <errno.h>
#include <stdint.h>
#include <stdio.h>
@@ -60,6 +59,7 @@ __FBSDID("$FreeBSD$");
#include "memalloc.h"
#include "error.h"
#include "mystring.h"
+#include "syntax.h"
#undef eflag
@@ -307,7 +307,7 @@ umaskcmd(int argc __unused, char **argv __unused)
out1fmt("%.4o\n", mask);
}
} else {
- if (isdigit(*ap)) {
+ if (is_digit(*ap)) {
mask = 0;
do {
if (*ap >= '8' || *ap < '0')
diff --git a/bin/sh/mkinit.c b/bin/sh/mkinit.c
index 1d1d93e..d73e0e2 100644
--- a/bin/sh/mkinit.c
+++ b/bin/sh/mkinit.c
@@ -101,7 +101,7 @@ struct block {
*/
struct event {
- const char *name; /* name of event (e.g. INIT) */
+ const char *name; /* name of event (e.g. RESET) */
const char *routine; /* name of routine called on event */
const char *comment; /* comment describing routine */
struct text code; /* code for handling event */
@@ -114,11 +114,6 @@ char writer[] = "\
*/\n\
\n";
-char init[] = "\
-/*\n\
- * Initialization code.\n\
- */\n";
-
char reset[] = "\
/*\n\
* This routine is called when an error or an interrupt occurs in an\n\
@@ -127,7 +122,6 @@ char reset[] = "\
struct event event[] = {
- { "INIT", "init", init, { NULL, 0, NULL, NULL } },
{ "RESET", "reset", reset, { NULL, 0, NULL, NULL } },
{ NULL, NULL, NULL, { NULL, 0, NULL, NULL } }
};
diff --git a/bin/sh/mksyntax.c b/bin/sh/mksyntax.c
index 07dc2f1..c6bf480 100644
--- a/bin/sh/mksyntax.c
+++ b/bin/sh/mksyntax.c
@@ -103,29 +103,19 @@ static char writer[] = "\
static FILE *cfile;
static FILE *hfile;
-static const char *syntax[513];
-static int base;
-static int size; /* number of values which a char variable can have */
-static int nbits; /* number of bits in a character */
-static int digit_contig;/* true if digits are contiguous */
-
-static void filltable(const char *);
-static void init(void);
+
+static void add_default(void);
+static void finish(void);
+static void init(const char *);
static void add(const char *, const char *);
-static void print(const char *);
static void output_type_macros(void);
-static void digit_convert(void);
int
main(int argc __unused, char **argv __unused)
{
- char c;
- char d;
- int sign;
int i;
char buf[80];
int pos;
- static char digit[] = "0123456789";
/* Create output files */
if ((cfile = fopen("syntax.c", "w")) == NULL) {
@@ -139,33 +129,8 @@ main(int argc __unused, char **argv __unused)
fputs(writer, hfile);
fputs(writer, cfile);
- /* Determine the characteristics of chars. */
- c = -1;
- sign = (c > 0) ? 0 : 1;
- for (nbits = 1 ; ; nbits++) {
- d = (1 << nbits) - 1;
- if (d == c)
- break;
- }
-#if 0
- printf("%s %d bit chars\n", sign? "signed" : "unsigned", nbits);
-#endif
- if (nbits > 9) {
- fputs("Characters can't have more than 9 bits\n", stderr);
- exit(2);
- }
- size = (1 << nbits) + 1;
- base = 1;
- if (sign)
- base += 1 << (nbits - 1);
- digit_contig = 1;
- for (i = 0 ; i < 10 ; i++) {
- if (digit[i] != '0' + i)
- digit_contig = 0;
- }
-
fputs("#include <sys/cdefs.h>\n", hfile);
- fputs("#include <ctype.h>\n", hfile);
+ fputs("#include <limits.h>\n\n", hfile);
/* Generate the #define statements in the header file */
fputs("/* Syntax classes */\n", hfile);
@@ -186,8 +151,8 @@ main(int argc __unused, char **argv __unused)
fprintf(hfile, "/* %s */\n", is_entry[i].comment);
}
putc('\n', hfile);
- fprintf(hfile, "#define SYNBASE %d\n", base);
- fprintf(hfile, "#define PEOF %d\n\n", -base);
+ fputs("#define SYNBASE (1 - CHAR_MIN)\n", hfile);
+ fputs("#define PEOF -SYNBASE\n\n", hfile);
putc('\n', hfile);
fputs("#define BASESYNTAX (basesyntax + SYNBASE)\n", hfile);
fputs("#define DQSYNTAX (dqsyntax + SYNBASE)\n", hfile);
@@ -198,10 +163,13 @@ main(int argc __unused, char **argv __unused)
putc('\n', hfile);
/* Generate the syntax tables. */
+ fputs("#include \"parser.h\"\n", cfile);
fputs("#include \"shell.h\"\n", cfile);
fputs("#include \"syntax.h\"\n\n", cfile);
- init();
+
fputs("/* syntax table used when not in quotes */\n", cfile);
+ init("basesyntax");
+ add_default();
add("\n", "CNL");
add("\\", "CBACK");
add("'", "CSQUOTE");
@@ -210,9 +178,11 @@ main(int argc __unused, char **argv __unused)
add("$", "CVAR");
add("}", "CENDVAR");
add("<>();&| \t", "CSPCL");
- print("basesyntax");
- init();
+ finish();
+
fputs("\n/* syntax table used when in double quotes */\n", cfile);
+ init("dqsyntax");
+ add_default();
add("\n", "CNL");
add("\\", "CBACK");
add("\"", "CENDQUOTE");
@@ -221,17 +191,21 @@ main(int argc __unused, char **argv __unused)
add("}", "CENDVAR");
/* ':/' for tilde expansion, '-^]' for [a\-x] pattern ranges */
add("!*?[]=~:/-^", "CCTL");
- print("dqsyntax");
- init();
+ finish();
+
fputs("\n/* syntax table used when in single quotes */\n", cfile);
+ init("sqsyntax");
+ add_default();
add("\n", "CNL");
add("\\", "CSBACK");
add("'", "CENDQUOTE");
/* ':/' for tilde expansion, '-^]' for [a\-x] pattern ranges */
add("!*?[]=~:/-^", "CCTL");
- print("sqsyntax");
- init();
+ finish();
+
fputs("\n/* syntax table used when in arithmetic */\n", cfile);
+ init("arisyntax");
+ add_default();
add("\n", "CNL");
add("\\", "CBACK");
add("`", "CBQUOTE");
@@ -240,114 +214,108 @@ main(int argc __unused, char **argv __unused)
add("}", "CENDVAR");
add("(", "CLP");
add(")", "CRP");
- print("arisyntax");
- filltable("0");
+ finish();
+
fputs("\n/* character classification table */\n", cfile);
+ init("is_type");
add("0123456789", "ISDIGIT");
add("abcdefghijklmnopqrstuvwxyz", "ISLOWER");
add("ABCDEFGHIJKLMNOPQRSTUVWXYZ", "ISUPPER");
add("_", "ISUNDER");
add("#?$!-*@", "ISSPECL");
- print("is_type");
- if (! digit_contig)
- digit_convert();
+ finish();
+
exit(0);
}
-
/*
- * Clear the syntax table.
+ * Output the header and declaration of a syntax table.
*/
static void
-filltable(const char *dftval)
+init(const char *name)
{
- int i;
+ fprintf(hfile, "extern const char %s[];\n", name);
+ fprintf(cfile, "const char %s[SYNBASE + CHAR_MAX + 1] = {\n", name);
+}
+
- for (i = 0 ; i < size ; i++)
- syntax[i] = dftval;
+static void
+add_one(const char *key, const char *type)
+{
+ fprintf(cfile, "\t[SYNBASE + %s] = %s,\n", key, type);
}
/*
- * Initialize the syntax table with default values.
+ * Add default values to the syntax table.
*/
static void
-init(void)
+add_default(void)
{
- filltable("CWORD");
- syntax[0] = "CEOF";
- syntax[base + CTLESC] = "CCTL";
- syntax[base + CTLVAR] = "CCTL";
- syntax[base + CTLENDVAR] = "CCTL";
- syntax[base + CTLBACKQ] = "CCTL";
- syntax[base + CTLBACKQ + CTLQUOTE] = "CCTL";
- syntax[base + CTLARI] = "CCTL";
- syntax[base + CTLENDARI] = "CCTL";
- syntax[base + CTLQUOTEMARK] = "CCTL";
- syntax[base + CTLQUOTEEND] = "CCTL";
+ add_one("PEOF", "CEOF");
+ add_one("CTLESC", "CCTL");
+ add_one("CTLVAR", "CCTL");
+ add_one("CTLENDVAR", "CCTL");
+ add_one("CTLBACKQ", "CCTL");
+ add_one("CTLBACKQ + CTLQUOTE", "CCTL");
+ add_one("CTLARI", "CCTL");
+ add_one("CTLENDARI", "CCTL");
+ add_one("CTLQUOTEMARK", "CCTL");
+ add_one("CTLQUOTEEND", "CCTL");
}
/*
- * Add entries to the syntax table.
+ * Output the footer of a syntax table.
*/
static void
-add(const char *p, const char *type)
+finish(void)
{
- while (*p)
- syntax[*p++ + base] = type;
+ fputs("};\n", cfile);
}
-
/*
- * Output the syntax table.
+ * Add entries to the syntax table.
*/
static void
-print(const char *name)
+add(const char *p, const char *type)
{
- int i;
- int col;
-
- fprintf(hfile, "extern const char %s[];\n", name);
- fprintf(cfile, "const char %s[%d] = {\n", name, size);
- col = 0;
- for (i = 0 ; i < size ; i++) {
- if (i == 0) {
- fputs(" ", cfile);
- } else if ((i & 03) == 0) {
- fputs(",\n ", cfile);
- col = 0;
- } else {
- putc(',', cfile);
- while (++col < 9 * (i & 03))
- putc(' ', cfile);
+ for (; *p; ++p) {
+ char c = *p;
+ switch (c) {
+ case '\t': c = 't'; break;
+ case '\n': c = 'n'; break;
+ case '\'': c = '\''; break;
+ case '\\': c = '\\'; break;
+
+ default:
+ fprintf(cfile, "\t[SYNBASE + '%c'] = %s,\n", c, type);
+ continue;
}
- fputs(syntax[i], cfile);
- col += strlen(syntax[i]);
+ fprintf(cfile, "\t[SYNBASE + '\\%c'] = %s,\n", c, type);
}
- fputs("\n};\n", cfile);
}
-
/*
* Output character classification macros (e.g. is_digit). If digits are
* contiguous, we can test for them quickly.
*/
static const char *macro[] = {
- "#define is_digit(c)\t((is_type+SYNBASE)[(int)c] & ISDIGIT)",
+ "#define is_digit(c)\t((unsigned int)((c) - '0') <= 9)",
"#define is_eof(c)\t((c) == PEOF)",
"#define is_alpha(c)\t((is_type+SYNBASE)[(int)c] & (ISUPPER|ISLOWER))",
"#define is_name(c)\t((is_type+SYNBASE)[(int)c] & (ISUPPER|ISLOWER|ISUNDER))",
"#define is_in_name(c)\t((is_type+SYNBASE)[(int)c] & (ISUPPER|ISLOWER|ISUNDER|ISDIGIT))",
"#define is_special(c)\t((is_type+SYNBASE)[(int)c] & (ISSPECL|ISDIGIT))",
+ "#define digit_val(c)\t((c) - '0')",
NULL
};
@@ -356,41 +324,6 @@ output_type_macros(void)
{
const char **pp;
- if (digit_contig)
- macro[0] = "#define is_digit(c)\t((unsigned int)((c) - '0') <= 9)";
for (pp = macro ; *pp ; pp++)
fprintf(hfile, "%s\n", *pp);
- if (digit_contig)
- fputs("#define digit_val(c)\t((c) - '0')\n", hfile);
- else
- fputs("#define digit_val(c)\t(digit_value[c])\n", hfile);
-}
-
-
-
-/*
- * Output digit conversion table (if digits are not contiguous).
- */
-
-static void
-digit_convert(void)
-{
- int maxdigit;
- static char digit[] = "0123456789";
- char *p;
- int i;
-
- maxdigit = 0;
- for (p = digit ; *p ; p++)
- if (*p > maxdigit)
- maxdigit = *p;
- fputs("extern const char digit_value[];\n", hfile);
- fputs("\n\nconst char digit_value[] = {\n", cfile);
- for (i = 0 ; i <= maxdigit ; i++) {
- for (p = digit ; *p && *p != i ; p++);
- if (*p == '\0')
- p = digit;
- fprintf(cfile, " %d,\n", (int)(p - digit));
- }
- fputs("};\n", cfile);
}
diff --git a/bin/sh/nodetypes b/bin/sh/nodetypes
index ae4bc4a..5e70c64 100644
--- a/bin/sh/nodetypes
+++ b/bin/sh/nodetypes
@@ -138,6 +138,7 @@ NXHERE nhere # fd<<!
next nodeptr # next redirection in list
fd int # file descriptor being redirected
doc nodeptr # input to command (NARG node)
+ expdoc temp char *expdoc # actual document (for NXHERE)
NNOT nnot # ! command (actually pipeline)
type int
diff --git a/bin/sh/output.c b/bin/sh/output.c
index b4dab51..d26adce 100644
--- a/bin/sh/output.c
+++ b/bin/sh/output.c
@@ -239,6 +239,20 @@ freestdout(void)
}
+int
+outiserror(struct output *file)
+{
+ return (file->flags & OUTPUT_ERR);
+}
+
+
+void
+outclearerror(struct output *file)
+{
+ file->flags &= ~OUTPUT_ERR;
+}
+
+
void
outfmt(struct output *file, const char *fmt, ...)
{
diff --git a/bin/sh/output.h b/bin/sh/output.h
index 5e3b048..51974d8 100644
--- a/bin/sh/output.h
+++ b/bin/sh/output.h
@@ -66,6 +66,8 @@ void emptyoutbuf(struct output *);
void flushall(void);
void flushout(struct output *);
void freestdout(void);
+int outiserror(struct output *);
+void outclearerror(struct output *);
void outfmt(struct output *, const char *, ...) __printflike(2, 3);
void out1fmt(const char *, ...) __printflike(1, 2);
void out2fmt_flush(const char *, ...) __printflike(1, 2);
diff --git a/bin/sh/parser.c b/bin/sh/parser.c
index ef1aa36..665b53f 100644
--- a/bin/sh/parser.c
+++ b/bin/sh/parser.c
@@ -240,9 +240,9 @@ list(int nlflag, int erflag)
n2 = andor();
tok = readtoken();
if (tok == TBACKGND) {
- if (n2->type == NPIPE) {
+ if (n2 != NULL && n2->type == NPIPE) {
n2->npipe.backgnd = 1;
- } else if (n2->type == NREDIR) {
+ } else if (n2 != NULL && n2->type == NREDIR) {
n2->type = NBACKGND;
} else {
n3 = (union node *)stalloc(sizeof (struct nredir));
@@ -286,7 +286,8 @@ list(int nlflag, int erflag)
tokpushback++;
}
checkkwd = CHKNL | CHKKWD | CHKALIAS;
- if (!nlflag && !erflag && tokendlist[peektoken()])
+ if (!nlflag && (erflag ? peektoken() == TEOF :
+ tokendlist[peektoken()]))
return ntop;
break;
case TEOF:
diff --git a/bin/sh/parser.h b/bin/sh/parser.h
index 9a996d0..f80d917 100644
--- a/bin/sh/parser.h
+++ b/bin/sh/parser.h
@@ -39,7 +39,7 @@
#define CTLENDVAR '\371'
#define CTLBACKQ '\372'
#define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
-/* CTLBACKQ | CTLQUOTE == '\205' */
+/* CTLBACKQ | CTLQUOTE == '\373' */
#define CTLARI '\374'
#define CTLENDARI '\375'
#define CTLQUOTEMARK '\376'
diff --git a/bin/sh/redir.c b/bin/sh/redir.c
index 915b2fc..c11cb71 100644
--- a/bin/sh/redir.c
+++ b/bin/sh/redir.c
@@ -251,18 +251,23 @@ movefd:
static int
openhere(union node *redir)
{
+ char *p;
int pip[2];
int len = 0;
if (pipe(pip) < 0)
error("Pipe call failed: %s", strerror(errno));
- if (redir->type == NHERE) {
- len = strlen(redir->nhere.doc->narg.text);
- if (len <= PIPESIZE) {
- xwrite(pip[1], redir->nhere.doc->narg.text, len);
- goto out;
- }
+
+ if (redir->type == NXHERE)
+ p = redir->nhere.expdoc;
+ else
+ p = redir->nhere.doc->narg.text;
+ len = strlen(p);
+ if (len <= PIPESIZE) {
+ xwrite(pip[1], p, len);
+ goto out;
}
+
if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
close(pip[0]);
signal(SIGINT, SIG_IGN);
@@ -270,10 +275,7 @@ openhere(union node *redir)
signal(SIGHUP, SIG_IGN);
signal(SIGTSTP, SIG_IGN);
signal(SIGPIPE, SIG_DFL);
- if (redir->type == NHERE)
- xwrite(pip[1], redir->nhere.doc->narg.text, len);
- else
- expandhere(redir->nhere.doc, pip[1]);
+ xwrite(pip[1], p, len);
_exit(0);
}
out:
diff --git a/bin/sh/sh.1 b/bin/sh/sh.1
index 1750267..09d94f3 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 July 15, 2012
+.Dd January 22, 2013
.Dt SH 1
.Os
.Sh NAME
@@ -138,10 +138,10 @@ variable to some file by placing the following line in the file
.Pa .profile
in the home directory,
substituting for
-.Pa .shinit
+.Pa .shrc
the filename desired:
.Pp
-.Dl "ENV=$HOME/.shinit; export ENV"
+.Dl "ENV=$HOME/.shrc; export ENV"
.Pp
The first non-option argument specified on the command line
will be treated as the
@@ -2219,10 +2219,6 @@ The shell maintains a hash table which remembers the locations of commands.
With no arguments whatsoever, the
.Ic hash
command prints out the contents of this table.
-Entries which have not been looked at since the last
-.Ic cd
-command are marked with an asterisk;
-it is possible for these entries to be invalid.
.Pp
With arguments, the
.Ic hash
@@ -2678,6 +2674,17 @@ Additionally, all environment variables are turned into shell variables
at startup,
which may affect the shell as described under
.Sx Special Variables .
+.Sh FILES
+.Bl -tag -width "/etc/suid_profileXX" -compact
+.It Pa ~/.profile
+User's login profile.
+.It Pa /etc/profile
+System login profile.
+.It Pa /etc/shells
+Shell database.
+.It Pa /etc/suid_profile
+Privileged shell profile.
+.El
.Sh EXIT STATUS
Errors that are detected by the shell, such as a syntax error, will
cause the shell to exit with a non-zero exit status.
@@ -2703,7 +2710,8 @@ will return the argument.
.Xr getrlimit 2 ,
.Xr umask 2 ,
.Xr wctype 3 ,
-.Xr editrc 5
+.Xr editrc 5 ,
+.Xr shells 5
.Sh HISTORY
A
.Nm
diff --git a/bin/sh/var.c b/bin/sh/var.c
index 48a0dc5..3f29a48 100644
--- a/bin/sh/var.c
+++ b/bin/sh/var.c
@@ -146,29 +146,11 @@ static int varequal(const char *, const char *);
static struct var *find_var(const char *, struct var ***, int *);
static int localevar(const char *);
-/*
- * Initialize the variable symbol tables and import the environment.
- */
-
-#ifdef mkinit
-INCLUDE "var.h"
-MKINIT char **environ;
-INIT {
- char **envp;
-
- initvar();
- for (envp = environ ; *envp ; envp++) {
- if (strchr(*envp, '=')) {
- setvareq(*envp, VEXPORT|VTEXTFIXED);
- }
- }
-}
-#endif
-
+extern char **environ;
/*
- * This routine initializes the builtin variables. It is called when the
- * shell is initialized.
+ * This routine initializes the builtin variables and imports the environment.
+ * It is called when the shell is initialized.
*/
void
@@ -178,6 +160,7 @@ initvar(void)
const struct varinit *ip;
struct var *vp;
struct var **vpp;
+ char **envp;
for (ip = varinit ; (vp = ip->var) != NULL ; ip++) {
if (find_var(ip->text, &vpp, &vp->name_len) != NULL)
@@ -201,6 +184,11 @@ initvar(void)
fmtstr(ppid, sizeof(ppid), "%d", (int)getppid());
setvarsafe("PPID", ppid, 0);
}
+ for (envp = environ ; *envp ; envp++) {
+ if (strchr(*envp, '=')) {
+ setvareq(*envp, VEXPORT|VTEXTFIXED);
+ }
+ }
}
/*
@@ -356,7 +344,7 @@ setvareq(char *s, int flags)
* a regular variable function callback, but why bother?
*
* Note: this assumes iflag is not set to 1 initially.
- * As part of init(), this is called before arguments
+ * As part of initvar(), this is called before arguments
* are looked at.
*/
if ((vp == &vmpath || (vp == &vmail && ! mpathset())) &&
diff --git a/bin/test/test.1 b/bin/test/test.1
index d73f794..885374e 100644
--- a/bin/test/test.1
+++ b/bin/test/test.1
@@ -32,7 +32,7 @@
.\" @(#)test.1 8.1 (Berkeley) 5/31/93
.\" $FreeBSD$
.\"
-.Dd September 10, 2010
+.Dd December 27, 2012
.Dt TEST 1
.Os
.Sh NAME
@@ -331,6 +331,13 @@ missing.
.It >1
An error occurred.
.El
+.Sh COMPATIBILITY
+For compatibility with some other implementations,
+the
+.Cm =
+primary can be substituted with
+.Cm ==
+with the same meaning.
.Sh SEE ALSO
.Xr builtin 1 ,
.Xr expr 1 ,
OpenPOWER on IntegriCloud