aboutsummaryrefslogtreecommitdiff
path: root/bin
diff options
context:
space:
mode:
authorSimon J. Gerraty <sjg@FreeBSD.org>2013-09-05 20:18:59 +0000
committerSimon J. Gerraty <sjg@FreeBSD.org>2013-09-05 20:18:59 +0000
commitd1d015864103b253b3fcb2f72a0da5b0cfeb31b6 (patch)
tree22b131dceb13c3df96da594fbaadb693504797c7 /bin
parent12d4083451fc39b3e831d4ea0bfa67d3b32cfb54 (diff)
parentb6f49c23a36f329cbf1e7f28078e17fd87f0e245 (diff)
downloadsrc-d1d015864103b253b3fcb2f72a0da5b0cfeb31b6.tar.gz
src-d1d015864103b253b3fcb2f72a0da5b0cfeb31b6.zip
Merge from head
Notes
Notes: svn path=/projects/bmake/; revision=255263
Diffstat (limited to 'bin')
-rw-r--r--bin/cat/cat.c3
-rw-r--r--bin/chflags/chflags.122
-rw-r--r--bin/chio/chio.c70
-rw-r--r--bin/dd/args.c1
-rw-r--r--bin/dd/conv_tab.c1
-rw-r--r--bin/dd/dd.c8
-rw-r--r--bin/dd/extern.h3
-rw-r--r--bin/dd/misc.c28
-rw-r--r--bin/dd/position.c3
-rw-r--r--bin/df/df.14
-rw-r--r--bin/df/df.c11
-rw-r--r--bin/domainname/domainname.114
-rw-r--r--bin/ed/ed.14
-rw-r--r--bin/ed/re.c2
-rw-r--r--bin/expr/Makefile2
-rw-r--r--bin/hostname/hostname.c2
-rw-r--r--bin/kenv/kenv.c12
-rw-r--r--bin/kill/kill.c2
-rw-r--r--bin/ln/ln.c8
-rw-r--r--bin/ls/ls.13
-rw-r--r--bin/mkdir/mkdir.c4
-rw-r--r--bin/pkill/pkill.17
-rw-r--r--bin/pkill/pkill.c43
-rw-r--r--bin/ps/keyword.c1
-rw-r--r--bin/ps/ps.13
-rw-r--r--bin/rm/rm.16
-rw-r--r--bin/rm/rm.c51
-rw-r--r--bin/sh/Makefile11
-rw-r--r--bin/sh/TOUR29
-rw-r--r--bin/sh/alias.c8
-rw-r--r--bin/sh/arith_yylex.c4
-rw-r--r--bin/sh/eval.c29
-rw-r--r--bin/sh/eval.h5
-rw-r--r--bin/sh/exec.c3
-rw-r--r--bin/sh/init.h36
-rw-r--r--bin/sh/input.c20
-rw-r--r--bin/sh/input.h1
-rw-r--r--bin/sh/jobs.c131
-rw-r--r--bin/sh/jobs.h2
-rw-r--r--bin/sh/main.c15
-rw-r--r--bin/sh/memalloc.c20
-rw-r--r--bin/sh/memalloc.h1
-rw-r--r--bin/sh/miscbltin.c23
-rw-r--r--bin/sh/mkinit.c480
-rw-r--r--bin/sh/output.c19
-rw-r--r--bin/sh/parser.c189
-rw-r--r--bin/sh/parser.h6
-rw-r--r--bin/sh/redir.c23
-rw-r--r--bin/sh/sh.155
-rw-r--r--bin/sh/shell.h1
-rw-r--r--bin/sh/trap.c18
-rw-r--r--bin/sh/trap.h1
-rw-r--r--bin/sh/var.c5
-rw-r--r--bin/sleep/sleep.c11
-rw-r--r--bin/test/test.187
-rw-r--r--bin/test/test.c184
56 files changed, 583 insertions, 1152 deletions
diff --git a/bin/cat/cat.c b/bin/cat/cat.c
index 9e12d3e4eee5..0daac7caec70 100644
--- a/bin/cat/cat.c
+++ b/bin/cat/cat.c
@@ -68,7 +68,7 @@ static int bflag, eflag, lflag, nflag, sflag, tflag, vflag;
static int rval;
static const char *filename;
-static void usage(void);
+static void usage(void) __dead2;
static void scanfiles(char *argv[], int cooked);
static void cook_cat(FILE *);
static void raw_cat(int);
@@ -153,6 +153,7 @@ main(int argc, char *argv[])
static void
usage(void)
{
+
fprintf(stderr, "usage: cat [-belnstuv] [file ...]\n");
exit(1);
/* NOTREACHED */
diff --git a/bin/chflags/chflags.1 b/bin/chflags/chflags.1
index fe9d700a903f..47d5b181b45d 100644
--- a/bin/chflags/chflags.1
+++ b/bin/chflags/chflags.1
@@ -32,7 +32,7 @@
.\" @(#)chflags.1 8.4 (Berkeley) 5/2/95
.\" $FreeBSD$
.\"
-.Dd March 3, 2006
+.Dd April 8, 2013
.Dt CHFLAGS 1
.Os
.Sh NAME
@@ -101,20 +101,36 @@ The following keywords are currently defined:
.Bl -tag -offset indent -width ".Cm opaque"
.It Cm arch , archived
set the archived flag (super-user only)
-.It Cm opaque
-set the opaque flag (owner or super-user only)
.It Cm nodump
set the nodump flag (owner or super-user only)
+.It Cm opaque
+set the opaque flag (owner or super-user only)
.It Cm sappnd , sappend
set the system append-only flag (super-user only)
.It Cm schg , schange , simmutable
set the system immutable flag (super-user only)
+.It Cm snapshot
+set the snapshot flag (filesystems do not allow changing this flag)
.It Cm sunlnk , sunlink
set the system undeletable flag (super-user only)
.It Cm uappnd , uappend
set the user append-only flag (owner or super-user only)
+.It Cm uarch , uarchive
+set the archive flag (owner or super-user only)
.It Cm uchg , uchange , uimmutable
set the user immutable flag (owner or super-user only)
+.It Cm uhidden , hidden
+set the hidden file attribute (owner or super-user only)
+.It Cm uoffline , offline
+set the offline file attribute (owner or super-user only)
+.It Cm urdonly , rdonly , readonly
+set the DOS, Windows and CIFS readonly flag (owner or super-user only)
+.It Cm usparse , sparse
+set the sparse file attribute (owner or super-user only)
+.It Cm usystem , system
+set the DOS, Windows and CIFS system flag (owner or super-user only)
+.It Cm ureparse , reparse
+set the Windows reparse point file attribute (owner or super-user only)
.It Cm uunlnk , uunlink
set the user undeletable flag (owner or super-user only)
.El
diff --git a/bin/chio/chio.c b/bin/chio/chio.c
index 9bb11d75f325..5a2a7ba215c3 100644
--- a/bin/chio/chio.c
+++ b/bin/chio/chio.c
@@ -54,6 +54,8 @@ __FBSDID("$FreeBSD$");
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <langinfo.h>
+#include <locale.h>
#include "defs.h"
#include "pathnames.h"
@@ -81,6 +83,7 @@ static int do_status(const char *, int, char **);
static int do_ielem(const char *, int, char **);
static int do_return(const char *, int, char **);
static int do_voltag(const char *, int, char **);
+static void print_designator(const char *, u_int8_t, u_int8_t);
#ifndef CHET_VT
#define CHET_VT 10 /* Completely Arbitrary */
@@ -723,6 +726,10 @@ do_status(const char *cname, int argc, char **argv)
putchar('?');
putchar('>');
}
+ if (ces->ces_designator_length > 0)
+ print_designator(ces->ces_designator,
+ ces->ces_code_set,
+ ces->ces_designator_length);
putchar('\n');
}
@@ -1177,3 +1184,66 @@ usage(void)
"arg1 arg2 [arg3 [...]]\n", getprogname());
exit(1);
}
+
+#define UTF8CODESET "UTF-8"
+
+static void
+print_designator(const char *designator, u_int8_t code_set,
+ u_int8_t designator_length)
+{
+ printf(" serial number: <");
+ switch (code_set) {
+ case CES_CODE_SET_ASCII: {
+ /*
+ * The driver insures that the string is always NUL terminated.
+ */
+ printf("%s", designator);
+ break;
+ }
+ case CES_CODE_SET_UTF_8: {
+ char *cs_native;
+
+ setlocale(LC_ALL, "");
+ cs_native = nl_langinfo(CODESET);
+
+ /* See if we can natively print UTF-8 */
+ if (strcmp(cs_native, UTF8CODESET) == 0)
+ cs_native = NULL;
+
+ if (cs_native == NULL) {
+ /* We can natively print UTF-8, so use printf. */
+ printf("%s", designator);
+ } else {
+ int i;
+
+ /*
+ * We can't natively print UTF-8. We should
+ * convert it to the terminal's codeset, but that
+ * requires iconv(3) and FreeBSD doesn't have
+ * iconv(3) in the base system yet. So we use %XX
+ * notation for non US-ASCII characters instead.
+ */
+ for (i = 0; i < designator_length &&
+ designator[i] != '\0'; i++) {
+ if ((unsigned char)designator[i] < 0x80)
+ printf("%c", designator[i]);
+ else
+ printf("%%%02x",
+ (unsigned char)designator[i]);
+ }
+ }
+ break;
+ }
+ case CES_CODE_SET_BINARY: {
+ int i;
+
+ for (i = 0; i < designator_length; i++)
+ printf("%02X%s", designator[i],
+ (i == designator_length - 1) ? "" : " ");
+ break;
+ }
+ default:
+ break;
+ }
+ printf(">");
+}
diff --git a/bin/dd/args.c b/bin/dd/args.c
index 161fbfcb0d48..cc702f9231a5 100644
--- a/bin/dd/args.c
+++ b/bin/dd/args.c
@@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
#include <errno.h>
#include <inttypes.h>
#include <limits.h>
+#include <signal.h>
#include <stdlib.h>
#include <string.h>
diff --git a/bin/dd/conv_tab.c b/bin/dd/conv_tab.c
index 07449fd0f572..ce585dfe97f8 100644
--- a/bin/dd/conv_tab.c
+++ b/bin/dd/conv_tab.c
@@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$");
#include <sys/types.h>
+#include <signal.h>
#include <stdint.h>
#include "dd.h"
diff --git a/bin/dd/dd.c b/bin/dd/dd.c
index 01b66fc2d5e5..7e5bd913a2df 100644
--- a/bin/dd/dd.c
+++ b/bin/dd/dd.c
@@ -81,6 +81,7 @@ size_t cbsz; /* conversion block size */
uintmax_t files_cnt = 1; /* # of files to copy */
const u_char *ctab; /* conversion table */
char fill_char; /* Character to fill with if defined */
+volatile sig_atomic_t need_summary;
int
main(int argc __unused, char *argv[])
@@ -89,7 +90,7 @@ main(int argc __unused, char *argv[])
jcl(argv);
setup();
- (void)signal(SIGINFO, summaryx);
+ (void)signal(SIGINFO, siginfo_handler);
(void)signal(SIGINT, terminate);
atexit(summary);
@@ -358,7 +359,7 @@ dd_in(void)
* than noerror, notrunc or sync are specified, the block
* is output without buffering as it is read.
*/
- if (ddflags & C_BS) {
+ if ((ddflags & ~(C_NOERROR | C_NOTRUNC | C_SYNC)) == C_BS) {
out.dbcnt = in.dbcnt;
dd_out(1);
in.dbcnt = 0;
@@ -375,6 +376,9 @@ dd_in(void)
in.dbp += in.dbrcnt;
(*cfunc)();
+ if (need_summary) {
+ summary();
+ }
}
}
diff --git a/bin/dd/extern.h b/bin/dd/extern.h
index 9c540ad36546..6984f6d3b828 100644
--- a/bin/dd/extern.h
+++ b/bin/dd/extern.h
@@ -43,7 +43,7 @@ void jcl(char **);
void pos_in(void);
void pos_out(void);
void summary(void);
-void summaryx(int);
+void siginfo_handler(int);
void terminate(int);
void unblock(void);
void unblock_close(void);
@@ -61,3 +61,4 @@ extern const u_char e2a_32V[], e2a_POSIX[];
extern const u_char a2ibm_32V[], a2ibm_POSIX[];
extern u_char casetab[];
extern char fill_char;
+extern volatile sig_atomic_t need_summary;
diff --git a/bin/dd/misc.c b/bin/dd/misc.c
index 8edc5a534c63..84cc5eed9a18 100644
--- a/bin/dd/misc.c
+++ b/bin/dd/misc.c
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
#include <errno.h>
#include <inttypes.h>
+#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -57,41 +58,32 @@ summary(void)
{
struct timeval tv;
double secs;
- char buf[100];
(void)gettimeofday(&tv, NULL);
secs = tv.tv_sec + tv.tv_usec * 1e-6 - st.start;
if (secs < 1e-6)
secs = 1e-6;
- /* Use snprintf(3) so that we don't reenter stdio(3). */
- (void)snprintf(buf, sizeof(buf),
+ (void)fprintf(stderr,
"%ju+%ju records in\n%ju+%ju records out\n",
st.in_full, st.in_part, st.out_full, st.out_part);
- (void)write(STDERR_FILENO, buf, strlen(buf));
- if (st.swab) {
- (void)snprintf(buf, sizeof(buf), "%ju odd length swab %s\n",
+ if (st.swab)
+ (void)fprintf(stderr, "%ju odd length swab %s\n",
st.swab, (st.swab == 1) ? "block" : "blocks");
- (void)write(STDERR_FILENO, buf, strlen(buf));
- }
- if (st.trunc) {
- (void)snprintf(buf, sizeof(buf), "%ju truncated %s\n",
+ if (st.trunc)
+ (void)fprintf(stderr, "%ju truncated %s\n",
st.trunc, (st.trunc == 1) ? "block" : "blocks");
- (void)write(STDERR_FILENO, buf, strlen(buf));
- }
- (void)snprintf(buf, sizeof(buf),
+ (void)fprintf(stderr,
"%ju bytes transferred in %.6f secs (%.0f bytes/sec)\n",
st.bytes, secs, st.bytes / secs);
- (void)write(STDERR_FILENO, buf, strlen(buf));
+ need_summary = 0;
}
/* ARGSUSED */
void
-summaryx(int notused __unused)
+siginfo_handler(int signo __unused)
{
- int save_errno = errno;
- summary();
- errno = save_errno;
+ need_summary = 1;
}
/* ARGSUSED */
diff --git a/bin/dd/position.c b/bin/dd/position.c
index a638597707dd..57bfde592b64 100644
--- a/bin/dd/position.c
+++ b/bin/dd/position.c
@@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
#include <err.h>
#include <errno.h>
#include <inttypes.h>
+#include <signal.h>
#include <unistd.h>
#include "dd.h"
@@ -91,6 +92,8 @@ pos_in(void)
}
} else
--cnt;
+ if (need_summary)
+ summary();
continue;
}
diff --git a/bin/df/df.1 b/bin/df/df.1
index 8d142483acce..b5cf859cb57a 100644
--- a/bin/df/df.1
+++ b/bin/df/df.1
@@ -196,7 +196,9 @@ If the value is outside, it will be set to the appropriate limit.
.Xr localeconv 3 ,
.Xr fstab 5 ,
.Xr mount 8 ,
-.Xr quot 8 .
+.Xr pstat 8 ,
+.Xr quot 8 ,
+.Xr swapinfo 8 .
.Sh STANDARDS
With the exception of most options,
the
diff --git a/bin/df/df.c b/bin/df/df.c
index 77b7a40da67b..13ef129cf09e 100644
--- a/bin/df/df.c
+++ b/bin/df/df.c
@@ -114,6 +114,7 @@ main(int argc, char *argv[])
fstype = "ufs";
(void)setlocale(LC_ALL, "");
+ memset(&maxwidths, 0, sizeof(maxwidths));
memset(&totalbuf, 0, sizeof(totalbuf));
totalbuf.f_bsize = DEV_BSIZE;
strlcpy(totalbuf.f_mntfromname, "total", MNAMELEN);
@@ -200,7 +201,7 @@ main(int argc, char *argv[])
} else {
/* just the filesystems specified on the command line */
mntbuf = malloc(argc * sizeof(*mntbuf));
- if (mntbuf == 0)
+ if (mntbuf == NULL)
err(1, "malloc()");
mntsize = 0;
/* continued in for loop below */
@@ -209,13 +210,13 @@ main(int argc, char *argv[])
/* iterate through specified filesystems */
for (; *argv; argv++) {
if (stat(*argv, &stbuf) < 0) {
- if ((mntpt = getmntpt(*argv)) == 0) {
+ if ((mntpt = getmntpt(*argv)) == NULL) {
warn("%s", *argv);
rv = 1;
continue;
}
} else if (S_ISCHR(stbuf.st_mode)) {
- if ((mntpt = getmntpt(*argv)) == 0) {
+ if ((mntpt = getmntpt(*argv)) == NULL) {
mdev.fspec = *argv;
mntpath = strdup("/tmp/df.XXXXXX");
if (mntpath == NULL) {
@@ -282,7 +283,7 @@ main(int argc, char *argv[])
mntbuf[mntsize++] = statfsbuf;
}
- bzero(&maxwidths, sizeof(maxwidths));
+ memset(&maxwidths, 0, sizeof(maxwidths));
for (i = 0; i < mntsize; i++) {
if (aflag || (mntbuf[i].f_flags & MNT_IGNORE) == 0) {
update_maxwidths(&maxwidths, &mntbuf[i]);
@@ -309,7 +310,7 @@ getmntpt(const char *name)
if (!strcmp(mntbuf[i].f_mntfromname, name))
return (mntbuf[i].f_mntonname);
}
- return (0);
+ return (NULL);
}
/*
diff --git a/bin/domainname/domainname.1 b/bin/domainname/domainname.1
index 0f9245077242..099a40e6111f 100644
--- a/bin/domainname/domainname.1
+++ b/bin/domainname/domainname.1
@@ -29,7 +29,7 @@
.\" From: @(#)hostname.1 8.1 (Berkeley) 5/31/93
.\" $FreeBSD$
.\"
-.Dd September 18, 1994
+.Dd April 22, 2013
.Dt DOMAINNAME 1
.Os
.Sh NAME
@@ -43,10 +43,11 @@ The
.Nm
utility prints the name of the current YP/NIS domain.
The super-user can
-set the domain name by supplying an argument; this is usually done in the
-network initialization script
-.Pa /etc/rc.network ,
-normally run at boot
+set the domain name by supplying an argument; this is usually done with the
+.Va nisdomainname
+variable in the
+.Pa /etc/rc.conf
+file, normally run at boot
time.
.Sh NOTES
The YP/NIS (formerly ``Yellow Pages'' but renamed for legal reasons)
@@ -54,7 +55,8 @@ domain name does not necessarily have anything to do with the Domain
Name System domain name, although they are often set equal for administrative
convenience.
.Sh SEE ALSO
-.Xr getdomainname 3
+.Xr getdomainname 3 ,
+.Xr rc.conf 5
.Sh HISTORY
The
.Nm
diff --git a/bin/ed/ed.1 b/bin/ed/ed.1
index dbfb3dda37f1..8342645997c9 100644
--- a/bin/ed/ed.1
+++ b/bin/ed/ed.1
@@ -914,9 +914,9 @@ that line.
.El
.Sh FILES
.Bl -tag -width /tmp/ed.* -compact
-.It /tmp/ed.*
+.It Pa /tmp/ed.*
buffer file
-.It ed.hup
+.It Pa ed.hup
the file to which
.Nm
attempts to write the buffer if the terminal hangs up
diff --git a/bin/ed/re.c b/bin/ed/re.c
index 08a330de3f87..03a343657bbf 100644
--- a/bin/ed/re.c
+++ b/bin/ed/re.c
@@ -89,7 +89,7 @@ extract_pattern(int delimiter)
default:
break;
case '[':
- if ((nd = parse_char_class(++nd)) == NULL) {
+ if ((nd = parse_char_class(nd + 1)) == NULL) {
errmsg = "unbalanced brackets ([])";
return NULL;
}
diff --git a/bin/expr/Makefile b/bin/expr/Makefile
index 544853e10a25..b86cf6686ab0 100644
--- a/bin/expr/Makefile
+++ b/bin/expr/Makefile
@@ -4,4 +4,6 @@ PROG= expr
SRCS= expr.y
YFLAGS=
+NO_WMISSING_VARIABLE_DECLARATIONS=
+
.include <bsd.prog.mk>
diff --git a/bin/hostname/hostname.c b/bin/hostname/hostname.c
index 87136eb5f408..ecc319db6b17 100644
--- a/bin/hostname/hostname.c
+++ b/bin/hostname/hostname.c
@@ -49,7 +49,7 @@ __FBSDID("$FreeBSD$");
#include <string.h>
#include <unistd.h>
-static void usage(void);
+static void usage(void) __dead2;
int
main(int argc, char *argv[])
diff --git a/bin/kenv/kenv.c b/bin/kenv/kenv.c
index 5ba9a5e413f6..dad8a91fb6d9 100644
--- a/bin/kenv/kenv.c
+++ b/bin/kenv/kenv.c
@@ -37,9 +37,9 @@ __FBSDID("$FreeBSD$");
static void usage(void);
static int kdumpenv(void);
-static int kgetenv(char *);
-static int ksetenv(char *, char *);
-static int kunsetenv(char *);
+static int kgetenv(const char *);
+static int ksetenv(const char *, char *);
+static int kunsetenv(const char *);
static int hflag = 0;
static int Nflag = 0;
@@ -170,7 +170,7 @@ kdumpenv(void)
}
static int
-kgetenv(char *env)
+kgetenv(const char *env)
{
char buf[1024];
int ret;
@@ -186,7 +186,7 @@ kgetenv(char *env)
}
static int
-ksetenv(char *env, char *val)
+ksetenv(const char *env, char *val)
{
int ret;
@@ -197,7 +197,7 @@ ksetenv(char *env, char *val)
}
static int
-kunsetenv(char *env)
+kunsetenv(const char *env)
{
int ret;
diff --git a/bin/kill/kill.c b/bin/kill/kill.c
index 671d1cb1fc87..2d41f7865e48 100644
--- a/bin/kill/kill.c
+++ b/bin/kill/kill.c
@@ -156,7 +156,7 @@ signame_to_signum(const char *sig)
{
int n;
- if (!strncasecmp(sig, "SIG", (size_t)3))
+ if (strncasecmp(sig, "SIG", 3) == 0)
sig += 3;
for (n = 1; n < sys_nsig; n++) {
if (!strcasecmp(sys_signame[n], sig))
diff --git a/bin/ln/ln.c b/bin/ln/ln.c
index 4169e6229c98..f50802a9f941 100644
--- a/bin/ln/ln.c
+++ b/bin/ln/ln.c
@@ -65,8 +65,8 @@ static int wflag; /* Warn if symlink target does not
* exist, and -f is not enabled. */
static char linkch;
-int linkit(const char *, const char *, int);
-void usage(void);
+static int linkit(const char *, const char *, int);
+static void usage(void);
int
main(int argc, char *argv[])
@@ -219,7 +219,7 @@ samedirent(const char *path1, const char *path2)
return sb1.st_dev == sb2.st_dev && sb1.st_ino == sb2.st_ino;
}
-int
+static int
linkit(const char *source, const char *target, int isdir)
{
struct stat sb;
@@ -347,7 +347,7 @@ linkit(const char *source, const char *target, int isdir)
return (0);
}
-void
+static void
usage(void)
{
(void)fprintf(stderr, "%s\n%s\n%s\n",
diff --git a/bin/ls/ls.1 b/bin/ls/ls.1
index 7c7265225e01..8b7672b996ce 100644
--- a/bin/ls/ls.1
+++ b/bin/ls/ls.1
@@ -232,6 +232,9 @@ output.
Include the file flags in a long
.Pq Fl l
output.
+See
+.Xr chflags 1
+for a list of file flags and their meanings.
.It Fl p
Write a slash
.Pq Ql /
diff --git a/bin/mkdir/mkdir.c b/bin/mkdir/mkdir.c
index fda9c24bffa8..ea192092b19d 100644
--- a/bin/mkdir/mkdir.c
+++ b/bin/mkdir/mkdir.c
@@ -135,7 +135,7 @@ main(int argc, char *argv[])
* Returns 1 if a directory has been created,
* 2 if it already existed, and 0 on failure.
*/
-int
+static int
build(char *path, mode_t omode)
{
struct stat sb;
@@ -208,7 +208,7 @@ build(char *path, mode_t omode)
return (retval);
}
-void
+static void
usage(void)
{
diff --git a/bin/pkill/pkill.1 b/bin/pkill/pkill.1
index db7d78c96d7b..1ca383fa395a 100644
--- a/bin/pkill/pkill.1
+++ b/bin/pkill/pkill.1
@@ -29,7 +29,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd February 11, 2010
+.Dd August 9, 2013
.Dt PKILL 1
.Os
.Sh NAME
@@ -44,6 +44,7 @@
.Op Fl N Ar system
.Op Fl P Ar ppid
.Op Fl U Ar uid
+.Op Fl c Ar class
.Op Fl d Ar delim
.Op Fl g Ar pgrp
.Op Fl j Ar jid
@@ -60,6 +61,7 @@
.Op Fl N Ar system
.Op Fl P Ar ppid
.Op Fl U Ar uid
+.Op Fl c Ar class
.Op Fl g Ar pgrp
.Op Fl j Ar jid
.Op Fl s Ar sid
@@ -130,6 +132,9 @@ or
process and all of its ancestors are excluded (unless
.Fl v
is used).
+.It Fl c Ar class
+Restrict matches to processes running with specified login class
+.Ar class .
.It Fl f
Match against full argument lists.
The default is to match against process names.
diff --git a/bin/pkill/pkill.c b/bin/pkill/pkill.c
index cd919762899c..23ac0e9d786b 100644
--- a/bin/pkill/pkill.c
+++ b/bin/pkill/pkill.c
@@ -79,12 +79,14 @@ enum listtype {
LT_TTY,
LT_PGRP,
LT_JID,
- LT_SID
+ LT_SID,
+ LT_CLASS
};
struct list {
SLIST_ENTRY(list) li_chain;
long li_number;
+ char *li_name;
};
SLIST_HEAD(listhead, list);
@@ -116,6 +118,7 @@ static struct listhead ppidlist = SLIST_HEAD_INITIALIZER(ppidlist);
static struct listhead tdevlist = SLIST_HEAD_INITIALIZER(tdevlist);
static struct listhead sidlist = SLIST_HEAD_INITIALIZER(sidlist);
static struct listhead jidlist = SLIST_HEAD_INITIALIZER(jidlist);
+static struct listhead classlist = SLIST_HEAD_INITIALIZER(classlist);
static void usage(void) __attribute__((__noreturn__));
static int killact(const struct kinfo_proc *);
@@ -179,7 +182,7 @@ main(int argc, char **argv)
execf = NULL;
coref = _PATH_DEVNULL;
- while ((ch = getopt(argc, argv, "DF:G:ILM:N:P:SU:ad:fg:ij:lnoqs:t:u:vx")) != -1)
+ while ((ch = getopt(argc, argv, "DF:G:ILM:N:P:SU:ac:d:fg:ij:lnoqs:t:u:vx")) != -1)
switch (ch) {
case 'D':
debug_opt++;
@@ -222,6 +225,10 @@ main(int argc, char **argv)
case 'a':
ancestors++;
break;
+ case 'c':
+ makelist(&classlist, LT_CLASS, optarg);
+ criteria = 1;
+ break;
case 'd':
if (!pgrep)
usage();
@@ -469,6 +476,20 @@ main(int argc, char **argv)
continue;
}
+ SLIST_FOREACH(li, &classlist, li_chain) {
+ /*
+ * We skip P_SYSTEM processes to match ps(1) output.
+ */
+ if ((kp->ki_flag & P_SYSTEM) == 0 &&
+ kp->ki_loginclass != NULL &&
+ strcmp(kp->ki_loginclass, li->li_name) == 0)
+ break;
+ }
+ if (SLIST_FIRST(&classlist) != NULL && li == NULL) {
+ selected[i] = 0;
+ continue;
+ }
+
if (argc == 0)
selected[i] = 1;
}
@@ -562,9 +583,9 @@ usage(void)
fprintf(stderr,
"usage: %s %s [-F pidfile] [-G gid] [-M core] [-N system]\n"
- " [-P ppid] [-U uid] [-g pgrp] [-j jid] [-s sid]\n"
- " [-t tty] [-u euid] pattern ...\n", getprogname(),
- ustr);
+ " [-P ppid] [-U uid] [-c class] [-g pgrp] [-j jid]\n"
+ " [-s sid] [-t tty] [-u euid] pattern ...\n",
+ getprogname(), ustr);
exit(STATUS_BADUSAGE);
}
@@ -664,8 +685,10 @@ makelist(struct listhead *head, enum listtype type, char *src)
SLIST_INSERT_HEAD(head, li, li_chain);
empty = 0;
- li->li_number = (uid_t)strtol(sp, &ep, 0);
- if (*ep == '\0') {
+ if (type != LT_CLASS)
+ li->li_number = (uid_t)strtol(sp, &ep, 0);
+
+ if (type != LT_CLASS && *ep == '\0') {
switch (type) {
case LT_PGRP:
if (li->li_number == 0)
@@ -750,6 +773,12 @@ foundtty: if ((st.st_mode & S_IFCHR) == 0)
errx(STATUS_BADUSAGE,
"Invalid jail ID `%s'", sp);
break;
+ case LT_CLASS:
+ li->li_number = -1;
+ li->li_name = strdup(sp);
+ if (li->li_name == NULL)
+ err(STATUS_ERROR, "Cannot allocate memory");
+ break;
default:
usage();
}
diff --git a/bin/ps/keyword.c b/bin/ps/keyword.c
index 5861129c82a8..21e679128382 100644
--- a/bin/ps/keyword.c
+++ b/bin/ps/keyword.c
@@ -87,6 +87,7 @@ static VAR var[] = {
{"etimes", "ELAPSED", NULL, USER, elapseds, 0, CHAR, NULL, 0},
{"euid", "", "uid", 0, NULL, 0, CHAR, NULL, 0},
{"f", "F", NULL, 0, kvar, KOFF(ki_flag), INT, "x", 0},
+ {"fib", "FIB", NULL, 0, kvar, KOFF(ki_fibnum), INT, "d", 0},
{"flags", "", "f", 0, NULL, 0, CHAR, NULL, 0},
{"gid", "GID", NULL, 0, kvar, KOFF(ki_groups), UINT, UIDFMT, 0},
{"group", "GROUP", NULL, LJUST, egroupname, 0, CHAR, NULL, 0},
diff --git a/bin/ps/ps.1 b/bin/ps/ps.1
index 1a364f5f752c..81a1f6d44ed2 100644
--- a/bin/ps/ps.1
+++ b/bin/ps/ps.1
@@ -512,6 +512,9 @@ elapsed running time, format
minutes:seconds.
.It Cm etimes
elapsed running time, in decimal integer seconds
+.It Cm fib
+default FIB number, see
+.Xr setfib 1
.It Cm flags
the process flags, in hexadecimal (alias
.Cm f )
diff --git a/bin/rm/rm.1 b/bin/rm/rm.1
index 3588f388da71..824b627dec40 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 March 15, 2013
+.Dd April 25, 2013
.Dt RM 1
.Os
.Sh NAME
@@ -42,7 +42,7 @@
.Sh SYNOPSIS
.Nm
.Op Fl f | i
-.Op Fl dIPRrvW
+.Op Fl dIPRrvWx
.Ar
.Nm unlink
.Ar file
@@ -132,6 +132,8 @@ Attempt to undelete the named files.
Currently, this option can only be used to recover
files covered by whiteouts in a union file system (see
.Xr undelete 2 ) .
+.It Fl x
+When removing a hierarchy, do not cross mount points.
.El
.Pp
The
diff --git a/bin/rm/rm.c b/bin/rm/rm.c
index a45005739de1..976b4eeb57c2 100644
--- a/bin/rm/rm.c
+++ b/bin/rm/rm.c
@@ -59,19 +59,19 @@ __FBSDID("$FreeBSD$");
#include <unistd.h>
static int dflag, eval, fflag, iflag, Pflag, vflag, Wflag, stdin_ok;
-static int rflag, Iflag;
+static int rflag, Iflag, xflag;
static uid_t uid;
static volatile sig_atomic_t info;
-int check(char *, char *, struct stat *);
-int check2(char **);
-void checkdot(char **);
-void checkslash(char **);
-void rm_file(char **);
-int rm_overwrite(char *, struct stat *);
-void rm_tree(char **);
+static int check(const char *, const char *, struct stat *);
+static int check2(char **);
+static void checkdot(char **);
+static void checkslash(char **);
+static void rm_file(char **);
+static int rm_overwrite(const char *, struct stat *);
+static void rm_tree(char **);
static void siginfo(int __unused);
-void usage(void);
+static void usage(void);
/*
* rm --
@@ -106,8 +106,8 @@ main(int argc, char *argv[])
exit(eval);
}
- Pflag = rflag = 0;
- while ((ch = getopt(argc, argv, "dfiIPRrvW")) != -1)
+ Pflag = rflag = xflag = 0;
+ while ((ch = getopt(argc, argv, "dfiIPRrvWx")) != -1)
switch(ch) {
case 'd':
dflag = 1;
@@ -136,6 +136,9 @@ main(int argc, char *argv[])
case 'W':
Wflag = 1;
break;
+ case 'x':
+ xflag = 1;
+ break;
default:
usage();
}
@@ -170,7 +173,7 @@ main(int argc, char *argv[])
exit (eval);
}
-void
+static void
rm_tree(char **argv)
{
FTS *fts;
@@ -196,6 +199,8 @@ rm_tree(char **argv)
flags |= FTS_NOSTAT;
if (Wflag)
flags |= FTS_WHITEOUT;
+ if (xflag)
+ flags |= FTS_XDEV;
if (!(fts = fts_open(argv, flags, NULL))) {
if (fflag && errno == ENOENT)
return;
@@ -335,7 +340,7 @@ err:
fts_close(fts);
}
-void
+static void
rm_file(char **argv)
{
struct stat sb;
@@ -412,8 +417,8 @@ rm_file(char **argv)
* System V file system). In a logging or COW file system, you'll have to
* have kernel support.
*/
-int
-rm_overwrite(char *file, struct stat *sbp)
+static int
+rm_overwrite(const char *file, struct stat *sbp)
{
struct stat sb, sb2;
struct statfs fsb;
@@ -479,8 +484,8 @@ err: eval = 1;
}
-int
-check(char *path, char *name, struct stat *sp)
+static int
+check(const char *path, const char *name, struct stat *sp)
{
int ch, first;
char modep[15], *flagsp;
@@ -491,7 +496,7 @@ check(char *path, char *name, struct stat *sp)
else {
/*
* If it's not a symbolic link and it's unwritable and we're
- * talking to a terminal, ask. Symbolic links are excluded
+ * talking to a terminal, ask. Symbolic links are excluded
* because their permissions are meaningless. Check stdin_ok
* first because we may not have stat'ed the file.
*/
@@ -524,7 +529,7 @@ check(char *path, char *name, struct stat *sp)
}
#define ISSLASH(a) ((a)[0] == '/' && (a)[1] == '\0')
-void
+static void
checkslash(char **argv)
{
char **t, **u;
@@ -544,7 +549,7 @@ checkslash(char **argv)
}
}
-int
+static int
check2(char **argv)
{
struct stat st;
@@ -595,7 +600,7 @@ check2(char **argv)
}
#define ISDOT(a) ((a)[0] == '.' && (!(a)[1] || ((a)[1] == '.' && !(a)[2])))
-void
+static void
checkdot(char **argv)
{
char *p, **save, **t;
@@ -619,12 +624,12 @@ checkdot(char **argv)
}
}
-void
+static void
usage(void)
{
(void)fprintf(stderr, "%s\n%s\n",
- "usage: rm [-f | -i] [-dIPRrvW] file ...",
+ "usage: rm [-f | -i] [-dIPRrvWx] file ...",
" unlink file");
exit(EX_USAGE);
}
diff --git a/bin/sh/Makefile b/bin/sh/Makefile
index cc04aa42db59..00d34fa749da 100644
--- a/bin/sh/Makefile
+++ b/bin/sh/Makefile
@@ -8,7 +8,7 @@ SHSRCS= alias.c arith_yacc.c arith_yylex.c cd.c echo.c error.c eval.c \
histedit.c input.c jobs.c kill.c mail.c main.c memalloc.c miscbltin.c \
mystring.c options.c output.c parser.c printf.c redir.c show.c \
test.c trap.c var.c
-GENSRCS= builtins.c init.c nodes.c syntax.c
+GENSRCS= builtins.c nodes.c syntax.c
GENHDRS= builtins.h nodes.h syntax.h token.h
SRCS= ${SHSRCS} ${GENSRCS} ${GENHDRS}
@@ -30,26 +30,21 @@ WFORMAT=0
${.CURDIR}/../test \
${.CURDIR}/../../usr.bin/printf
-CLEANFILES+= mkinit mkinit.o mknodes mknodes.o \
+CLEANFILES+= mknodes mknodes.o \
mksyntax mksyntax.o
CLEANFILES+= ${GENSRCS} ${GENHDRS}
-build-tools: mkinit mknodes mksyntax
+build-tools: mknodes mksyntax
.ORDER: builtins.c builtins.h
builtins.c builtins.h: mkbuiltins builtins.def
sh ${.CURDIR}/mkbuiltins ${.CURDIR}
-init.c: mkinit alias.c eval.c exec.c input.c jobs.c options.c parser.c \
- redir.c trap.c var.c
- ./mkinit ${.ALLSRC:S/^mkinit$//}
-
# XXX this is just to stop the default .c rule being used, so that the
# intermediate object has a fixed name.
# XXX we have a default .c rule, but no default .o rule.
.o:
${CC} ${CFLAGS} ${LDFLAGS} ${.IMPSRC} ${LDLIBS} -o ${.TARGET}
-mkinit: mkinit.o
mknodes: mknodes.o
mksyntax: mksyntax.o
diff --git a/bin/sh/TOUR b/bin/sh/TOUR
index 13438b528bc3..e9bbe9b121b5 100644
--- a/bin/sh/TOUR
+++ b/bin/sh/TOUR
@@ -25,38 +25,11 @@ programs is:
program input files generates
------- ----------- ---------
mkbuiltins builtins builtins.h builtins.c
- mkinit *.c init.c
mknodes nodetypes nodes.h nodes.c
mksyntax - syntax.h syntax.c
mktokens - token.h
-There are undoubtedly too many of these. Mkinit searches all the
-C source files for entries looking like:
-
- RESET {
- x = 2; /* executed when the shell does a longjmp
- back to the main command loop */
- }
-
-It pulls this code out into routines which are when particular
-events occur. The intent is to improve modularity by isolating
-the information about which modules need to be explicitly
-initialized/reset within the modules themselves.
-
-Mkinit recognizes several constructs for placing declarations in
-the init.c file.
- INCLUDE "file.h"
-includes a file. The storage class MKINIT makes a declaration
-available in the init.c file, for example:
- MKINIT int funcnest; /* depth of function calls */
-MKINIT alone on a line introduces a structure or union declara-
-tion:
- MKINIT
- struct redirtab {
- short renamed[10];
- };
-Preprocessor #define statements are copied to init.c without any
-special action to request this.
+There are undoubtedly too many of these.
EXCEPTIONS: Code for dealing with exceptions appears in
exceptions.c. The C language doesn't include exception handling,
diff --git a/bin/sh/alias.c b/bin/sh/alias.c
index da995bbd4733..044c869ed940 100644
--- a/bin/sh/alias.c
+++ b/bin/sh/alias.c
@@ -237,17 +237,19 @@ printaliases(void)
}
int
-aliascmd(int argc, char **argv)
+aliascmd(int argc __unused, char **argv __unused)
{
char *n, *v;
int ret = 0;
struct alias *ap;
- if (argc == 1) {
+ nextopt("");
+
+ if (*argptr == NULL) {
printaliases();
return (0);
}
- while ((n = *++argv) != NULL) {
+ while ((n = *argptr++) != NULL) {
if ((v = strchr(n+1, '=')) == NULL) /* n+1: funny ksh stuff */
if ((ap = lookupalias(n, 0)) == NULL) {
warning("%s: not found", n);
diff --git a/bin/sh/arith_yylex.c b/bin/sh/arith_yylex.c
index f6eebdba2640..ad0818426de5 100644
--- a/bin/sh/arith_yylex.c
+++ b/bin/sh/arith_yylex.c
@@ -218,9 +218,13 @@ checkeqcur:
value += ARITH_REM - '%';
goto checkeq;
case '+':
+ if (buf[1] == '+')
+ return ARITH_BAD;
value += ARITH_ADD - '+';
goto checkeq;
case '-':
+ if (buf[1] == '-')
+ return ARITH_BAD;
value += ARITH_SUB - '-';
goto checkeq;
case '~':
diff --git a/bin/sh/eval.c b/bin/sh/eval.c
index d3708b3bd140..b8f76d57f3d8 100644
--- a/bin/sh/eval.c
+++ b/bin/sh/eval.c
@@ -76,7 +76,7 @@ __FBSDID("$FreeBSD$");
int evalskip; /* set if we are skipping commands */
int skipcount; /* number of levels to skip */
-MKINIT int loopnest; /* current loop nesting level */
+static int loopnest; /* current loop nesting level */
int funcnest; /* depth of function calls */
static int builtin_flags; /* evalcommand flags for builtins */
@@ -104,16 +104,12 @@ static void prehash(union node *);
* Called to reset things after an exception.
*/
-#ifdef mkinit
-INCLUDE "eval.h"
-
-RESET {
+void
+reseteval(void)
+{
evalskip = 0;
loopnest = 0;
- funcnest = 0;
}
-#endif
-
/*
@@ -328,7 +324,7 @@ skipping: if (evalskip == SKIPCONT && --skipcount <= 0) {
}
if (evalskip == SKIPBREAK && --skipcount <= 0)
evalskip = 0;
- if (evalskip == SKIPFUNC || evalskip == SKIPFILE)
+ if (evalskip == SKIPRETURN)
status = exitstatus;
break;
}
@@ -589,7 +585,8 @@ evalpipe(union node *n)
pip[1] = -1;
if (lp->next) {
if (pipe(pip) < 0) {
- close(prevfd);
+ if (prevfd >= 0)
+ close(prevfd);
error("Pipe call failed: %s", strerror(errno));
}
}
@@ -1071,7 +1068,7 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
funcnest--;
popredir();
INTON;
- if (evalskip == SKIPFUNC) {
+ if (evalskip == SKIPRETURN) {
evalskip = 0;
skipcount = 0;
}
@@ -1308,14 +1305,8 @@ returncmd(int argc, char **argv)
{
int ret = argc > 1 ? number(argv[1]) : oexitstatus;
- if (funcnest) {
- evalskip = SKIPFUNC;
- skipcount = 1;
- } else {
- /* skip the rest of the file */
- evalskip = SKIPFILE;
- skipcount = 1;
- }
+ evalskip = SKIPRETURN;
+ skipcount = 1;
return ret;
}
diff --git a/bin/sh/eval.h b/bin/sh/eval.h
index 724e15714bf5..4129757e9f01 100644
--- a/bin/sh/eval.h
+++ b/bin/sh/eval.h
@@ -46,6 +46,8 @@ struct backcmd { /* result of evalbackcmd */
struct job *jp; /* job structure for command */
};
+void reseteval(void);
+
/* flags in argument to evaltree/evalstring */
#define EV_EXIT 01 /* exit after evaluating tree */
#define EV_TESTED 02 /* exit status is checked; ignore -e flag */
@@ -65,5 +67,4 @@ extern int skipcount;
/* reasons for skipping commands (see comment on breakcmd routine) */
#define SKIPBREAK 1
#define SKIPCONT 2
-#define SKIPFUNC 3
-#define SKIPFILE 4
+#define SKIPRETURN 3
diff --git a/bin/sh/exec.c b/bin/sh/exec.c
index 6c3a6ddbf783..9f8e029933eb 100644
--- a/bin/sh/exec.c
+++ b/bin/sh/exec.c
@@ -70,7 +70,6 @@ __FBSDID("$FreeBSD$");
#include "syntax.h"
#include "memalloc.h"
#include "error.h"
-#include "init.h"
#include "mystring.h"
#include "show.h"
#include "jobs.h"
@@ -763,5 +762,7 @@ typecmd_impl(int argc, char **argv, int cmd, const char *path)
int
typecmd(int argc, char **argv)
{
+ if (argc > 2 && strcmp(argv[1], "--") == 0)
+ argc--, argv++;
return typecmd_impl(argc, argv, TYPECMD_TYPE, bltinlookup("PATH", 1));
}
diff --git a/bin/sh/init.h b/bin/sh/init.h
deleted file mode 100644
index 384bb699feaa..000000000000
--- a/bin/sh/init.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*-
- * Copyright (c) 1991, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)init.h 8.2 (Berkeley) 5/4/95
- * $FreeBSD$
- */
-
-void reset(void);
diff --git a/bin/sh/input.c b/bin/sh/input.c
index 62e82a0dbda6..e46095d5ed54 100644
--- a/bin/sh/input.c
+++ b/bin/sh/input.c
@@ -92,7 +92,7 @@ struct parsefile {
int plinno = 1; /* input line number */
int parsenleft; /* copy of parsefile->nleft */
-MKINIT int parselleft; /* copy of parsefile->lleft */
+static int parselleft; /* copy of parsefile->lleft */
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 */
@@ -108,15 +108,12 @@ static void pushfile(void);
static int preadfd(void);
static void popstring(void);
-#ifdef mkinit
-INCLUDE "input.h"
-INCLUDE "error.h"
-
-RESET {
+void
+resetinput(void)
+{
popallfiles();
parselleft = parsenleft = 0; /* clear input buffer */
}
-#endif
/*
@@ -397,10 +394,10 @@ setinputfile(const char *fname, int push)
int fd2;
INTOFF;
- if ((fd = open(fname, O_RDONLY)) < 0)
+ if ((fd = open(fname, O_RDONLY | O_CLOEXEC)) < 0)
error("cannot open %s: %s", fname, strerror(errno));
if (fd < 10) {
- fd2 = fcntl(fd, F_DUPFD, 10);
+ fd2 = fcntl(fd, F_DUPFD_CLOEXEC, 10);
close(fd);
if (fd2 < 0)
error("Out of file descriptors");
@@ -412,14 +409,13 @@ setinputfile(const char *fname, int push)
/*
- * Like setinputfile, but takes an open file descriptor. Call this with
- * interrupts off.
+ * Like setinputfile, but takes an open file descriptor (which should have
+ * its FD_CLOEXEC flag already set). Call this with interrupts off.
*/
void
setinputfd(int fd, int push)
{
- (void)fcntl(fd, F_SETFD, FD_CLOEXEC);
if (push) {
pushfile();
parsefile->buf = ckmalloc(BUFSIZ + 1);
diff --git a/bin/sh/input.h b/bin/sh/input.h
index 70f675e5cbfb..cc54eedb185a 100644
--- a/bin/sh/input.h
+++ b/bin/sh/input.h
@@ -47,6 +47,7 @@ extern const char *parsenextc; /* next character in input buffer */
struct alias;
struct parsefile;
+void resetinput(void);
char *pfgets(char *, int);
int pgetc(void);
int preadbuffer(void);
diff --git a/bin/sh/jobs.c b/bin/sh/jobs.c
index c978e3d643a0..bbb954ac0a1a 100644
--- a/bin/sh/jobs.c
+++ b/bin/sh/jobs.c
@@ -77,24 +77,25 @@ __FBSDID("$FreeBSD$");
static struct job *jobtab; /* array of jobs */
static int njobs; /* size of array */
-MKINIT pid_t backgndpid = -1; /* pid of last background process */
-MKINIT struct job *bgjob = NULL; /* last background process */
+static pid_t backgndpid = -1; /* pid of last background process */
+static struct job *bgjob = NULL; /* last background process */
#if JOBS
static struct job *jobmru; /* most recently used job list */
static pid_t initialpgrp; /* pgrp of shell on invocation */
#endif
-int in_waitcmd = 0; /* are we in waitcmd()? */
-volatile sig_atomic_t breakwaitcmd = 0; /* should wait be terminated? */
static int ttyfd = -1;
/* mode flags for dowait */
#define DOWAIT_BLOCK 0x1 /* wait until a child exits */
-#define DOWAIT_SIG 0x2 /* if DOWAIT_BLOCK, abort on signals */
+#define DOWAIT_SIG 0x2 /* if DOWAIT_BLOCK, abort on SIGINT/SIGQUIT */
+#define DOWAIT_SIG_ANY 0x4 /* if DOWAIT_SIG, abort on any signal */
#if JOBS
static void restartjob(struct job *);
#endif
static void freejob(struct job *);
+static int waitcmdloop(struct job *);
+static struct job *getjob_nonotfound(char *);
static struct job *getjob(char *);
pid_t getjobpgrp(char *);
static pid_t dowait(int, struct job *);
@@ -114,7 +115,7 @@ static void showjob(struct job *, int);
* Turn job control on and off.
*/
-MKINIT int jobctl;
+static int jobctl;
#if JOBS
void
@@ -127,11 +128,12 @@ setjobctl(int on)
if (on) {
if (ttyfd != -1)
close(ttyfd);
- if ((ttyfd = open(_PATH_TTY, O_RDWR)) < 0) {
+ if ((ttyfd = open(_PATH_TTY, O_RDWR | O_CLOEXEC)) < 0) {
i = 0;
while (i <= 2 && !isatty(i))
i++;
- if (i > 2 || (ttyfd = fcntl(i, F_DUPFD, 10)) < 0)
+ if (i > 2 ||
+ (ttyfd = fcntl(i, F_DUPFD_CLOEXEC, 10)) < 0)
goto out;
}
if (ttyfd < 10) {
@@ -139,7 +141,7 @@ setjobctl(int on)
* Keep our TTY file descriptor out of the way of
* the user's redirections.
*/
- if ((i = fcntl(ttyfd, F_DUPFD, 10)) < 0) {
+ if ((i = fcntl(ttyfd, F_DUPFD_CLOEXEC, 10)) < 0) {
close(ttyfd);
ttyfd = -1;
goto out;
@@ -147,11 +149,6 @@ setjobctl(int on)
close(ttyfd);
ttyfd = i;
}
- if (fcntl(ttyfd, F_SETFD, FD_CLOEXEC) < 0) {
- close(ttyfd);
- ttyfd = -1;
- goto out;
- }
do { /* while we are in the background */
initialpgrp = tcgetpgrp(ttyfd);
if (initialpgrp < 0) {
@@ -185,13 +182,14 @@ out: out2fmt_flush("sh: can't access tty; job control turned off\n");
#if JOBS
int
-fgcmd(int argc __unused, char **argv)
+fgcmd(int argc __unused, char **argv __unused)
{
struct job *jp;
pid_t pgrp;
int status;
- jp = getjob(argv[1]);
+ nextopt("");
+ jp = getjob(*argptr);
if (jp->jobctl == 0)
error("job not created under job control");
printjobcmd(jp);
@@ -212,8 +210,9 @@ bgcmd(int argc, char **argv)
{
struct job *jp;
+ nextopt("");
do {
- jp = getjob(*++argv);
+ jp = getjob(*argptr);
if (jp->jobctl == 0)
error("job not created under job control");
if (jp->state == JOBDONE)
@@ -222,7 +221,7 @@ bgcmd(int argc, char **argv)
jp->foreground = 0;
out1fmt("[%td] ", jp - jobtab + 1);
printjobcmd(jp);
- } while (--argc > 1);
+ } while (*argptr != NULL && *++argptr != NULL);
return 0;
}
@@ -417,13 +416,15 @@ showjobs(int change, int mode)
if (change && ! jp->changed)
continue;
showjob(jp, mode);
- jp->changed = 0;
- /* Hack: discard jobs for which $! has not been referenced
- * in interactive mode when they terminate.
- */
- if (jp->state == JOBDONE && !jp->remembered &&
- (iflag || jp != bgjob)) {
- freejob(jp);
+ if (mode == SHOWJOBS_DEFAULT || mode == SHOWJOBS_VERBOSE) {
+ jp->changed = 0;
+ /* Hack: discard jobs for which $! has not been
+ * referenced in interactive mode when they terminate.
+ */
+ if (jp->state == JOBDONE && !jp->remembered &&
+ (iflag || jp != bgjob)) {
+ freejob(jp);
+ }
}
}
}
@@ -461,32 +462,41 @@ int
waitcmd(int argc __unused, char **argv __unused)
{
struct job *job;
- int status, retval;
- struct job *jp;
+ int retval;
nextopt("");
- if (*argptr != NULL) {
- job = getjob(*argptr);
- } else {
- job = NULL;
- }
+ if (*argptr == NULL)
+ return (waitcmdloop(NULL));
+
+ do {
+ job = getjob_nonotfound(*argptr);
+ if (job == NULL)
+ retval = 127;
+ else
+ retval = waitcmdloop(job);
+ argptr++;
+ } while (*argptr != NULL);
+
+ return (retval);
+}
+
+static int
+waitcmdloop(struct job *job)
+{
+ int status, retval, sig;
+ struct job *jp;
/*
* Loop until a process is terminated or stopped, or a SIGINT is
* received.
*/
- in_waitcmd++;
do {
if (job != NULL) {
- if (job->state) {
+ if (job->state == JOBDONE) {
status = job->ps[job->nprocs - 1].status;
if (WIFEXITED(status))
retval = WEXITSTATUS(status);
-#if JOBS
- else if (WIFSTOPPED(status))
- retval = WSTOPSIG(status) + 128;
-#endif
else
retval = WTERMSIG(status) + 128;
if (! iflag || ! job->changed)
@@ -496,7 +506,6 @@ waitcmd(int argc __unused, char **argv __unused)
if (job == bgjob)
bgjob = NULL;
}
- in_waitcmd--;
return retval;
}
} else {
@@ -512,7 +521,6 @@ waitcmd(int argc __unused, char **argv __unused)
}
for (jp = jobtab ; ; jp++) {
if (jp >= jobtab + njobs) { /* no running procs */
- in_waitcmd--;
return 0;
}
if (jp->used && jp->state == 0)
@@ -520,20 +528,22 @@ waitcmd(int argc __unused, char **argv __unused)
}
}
} while (dowait(DOWAIT_BLOCK | DOWAIT_SIG, (struct job *)NULL) != -1);
- in_waitcmd--;
- return pendingsig + 128;
+ sig = pendingsig_waitcmd;
+ pendingsig_waitcmd = 0;
+ return sig + 128;
}
int
-jobidcmd(int argc __unused, char **argv)
+jobidcmd(int argc __unused, char **argv __unused)
{
struct job *jp;
int i;
- jp = getjob(argv[1]);
+ nextopt("");
+ jp = getjob(*argptr);
for (i = 0 ; i < jp->nprocs ; ) {
out1fmt("%d", (int)jp->ps[i].pid);
out1c(++i < jp->nprocs? ' ' : '\n');
@@ -548,7 +558,7 @@ jobidcmd(int argc __unused, char **argv)
*/
static struct job *
-getjob(char *name)
+getjob_nonotfound(char *name)
{
int jobno;
struct job *found, *jp;
@@ -613,12 +623,22 @@ currentjob: if ((jp = getcurjob(NULL)) == NULL)
return jp;
}
}
- error("No such job: %s", name);
- /*NOTREACHED*/
return NULL;
}
+static struct job *
+getjob(char *name)
+{
+ struct job *jp;
+
+ jp = getjob_nonotfound(name);
+ if (jp == NULL)
+ error("No such job: %s", name);
+ return (jp);
+}
+
+
pid_t
getjobpgrp(char *name)
{
@@ -967,7 +987,8 @@ waitforjob(struct job *jp, int *origstatus)
INTOFF;
TRACE(("waitforjob(%%%td) called\n", jp - jobtab + 1));
while (jp->state == 0)
- if (dowait(DOWAIT_BLOCK | (Tflag ? DOWAIT_SIG : 0), jp) == -1)
+ if (dowait(DOWAIT_BLOCK | (Tflag ? DOWAIT_SIG |
+ DOWAIT_SIG_ANY : 0), jp) == -1)
dotrap();
#if JOBS
if (jp->jobctl) {
@@ -1058,12 +1079,17 @@ dowait(int mode, struct job *job)
pid = wait3(&status, wflags, (struct rusage *)NULL);
TRACE(("wait returns %d, status=%d\n", (int)pid, status));
if (pid == 0 && (mode & DOWAIT_SIG) != 0) {
- sigsuspend(&omask);
pid = -1;
+ if (((mode & DOWAIT_SIG_ANY) != 0 ?
+ pendingsig : pendingsig_waitcmd) != 0) {
+ errno = EINTR;
+ break;
+ }
+ sigsuspend(&omask);
if (int_pending())
break;
}
- } while (pid == -1 && errno == EINTR && breakwaitcmd == 0);
+ } while (pid == -1 && errno == EINTR);
if (pid == -1 && errno == ECHILD && job != NULL)
job->state = JOBDONE;
if ((mode & DOWAIT_SIG) != 0) {
@@ -1072,11 +1098,6 @@ dowait(int mode, struct job *job)
sigprocmask(SIG_SETMASK, &omask, NULL);
INTON;
}
- if (breakwaitcmd != 0) {
- breakwaitcmd = 0;
- if (pid <= 0)
- return -1;
- }
if (pid <= 0)
return pid;
INTOFF;
diff --git a/bin/sh/jobs.h b/bin/sh/jobs.h
index 1570b4695dad..892f12916eb9 100644
--- a/bin/sh/jobs.h
+++ b/bin/sh/jobs.h
@@ -83,8 +83,6 @@ enum {
};
extern int job_warning; /* user was warned about stopped jobs */
-extern int in_waitcmd; /* are we in waitcmd()? */
-extern volatile sig_atomic_t breakwaitcmd; /* break wait to process traps? */
void setjobctl(int);
void showjobs(int, int);
diff --git a/bin/sh/main.c b/bin/sh/main.c
index 84a1ef2d0fbb..e4974ea7f455 100644
--- a/bin/sh/main.c
+++ b/bin/sh/main.c
@@ -68,10 +68,10 @@ __FBSDID("$FreeBSD$");
#include "show.h"
#include "memalloc.h"
#include "error.h"
-#include "init.h"
#include "mystring.h"
#include "exec.h"
#include "cd.h"
+#include "redir.h"
#include "builtins.h"
int rootpid;
@@ -79,6 +79,7 @@ int rootshell;
struct jmploc main_handler;
int localeisutf8, initial_localeisutf8;
+static void reset(void);
static void cmdloop(int);
static void read_profile(const char *);
static char *find_dot_file(char *);
@@ -170,8 +171,8 @@ state3:
if (minusc) {
evalstring(minusc, sflag ? 0 : EV_EXIT);
}
+state4:
if (sflag || minusc == NULL) {
-state4: /* XXX ??? - why isn't this before the "if" statement */
cmdloop(1);
}
exitshell(exitstatus);
@@ -179,6 +180,12 @@ state4: /* XXX ??? - why isn't this before the "if" statement */
return 0;
}
+static void
+reset(void)
+{
+ reseteval();
+ resetinput();
+}
/*
* Read and execute commands. "Top" is nonzero for the top level command
@@ -224,7 +231,7 @@ cmdloop(int top)
popstackmark(&smark);
setstackmark(&smark);
if (evalskip != 0) {
- if (evalskip == SKIPFILE)
+ if (evalskip == SKIPRETURN)
evalskip = 0;
break;
}
@@ -248,7 +255,7 @@ read_profile(const char *name)
if (expandedname == NULL)
return;
INTOFF;
- if ((fd = open(expandedname, O_RDONLY)) >= 0)
+ if ((fd = open(expandedname, O_RDONLY | O_CLOEXEC)) >= 0)
setinputfd(fd, 1);
INTON;
if (fd < 0)
diff --git a/bin/sh/memalloc.c b/bin/sh/memalloc.c
index f33a15ced528..cb330d0ec0fa 100644
--- a/bin/sh/memalloc.c
+++ b/bin/sh/memalloc.c
@@ -124,7 +124,6 @@ struct stack_block {
#define SPACE(sp) ((char*)(sp) + ALIGN(sizeof(struct stack_block)))
static struct stack_block *stackp;
-static struct stackmark *markp;
char *stacknxt;
int stacknleft;
char *sstrend;
@@ -186,8 +185,9 @@ setstackmark(struct stackmark *mark)
mark->stackp = stackp;
mark->stacknxt = stacknxt;
mark->stacknleft = stacknleft;
- mark->marknext = markp;
- markp = mark;
+ /* Ensure this block stays in place. */
+ if (stackp != NULL && stacknxt == SPACE(stackp))
+ stalloc(1);
}
@@ -197,7 +197,6 @@ popstackmark(struct stackmark *mark)
struct stack_block *sp;
INTOFF;
- markp = mark->marknext;
while (stackp != mark->stackp) {
sp = stackp;
stackp = sp->prev;
@@ -229,7 +228,6 @@ growstackblock(int min)
int oldlen;
struct stack_block *sp;
struct stack_block *oldstackp;
- struct stackmark *xmark;
if (min < stacknleft)
min = stacknleft;
@@ -254,18 +252,6 @@ growstackblock(int min)
stacknxt = SPACE(sp);
stacknleft = newlen - (stacknxt - (char*)sp);
sstrend = stacknxt + stacknleft;
-
- /*
- * Stack marks pointing to the start of the old block
- * must be relocated to point to the new block
- */
- xmark = markp;
- while (xmark != NULL && xmark->stackp == oldstackp) {
- xmark->stackp = stackp;
- xmark->stacknxt = stacknxt;
- xmark->stacknleft = stacknleft;
- xmark = xmark->marknext;
- }
INTON;
} else {
newlen -= ALIGN(sizeof(struct stack_block));
diff --git a/bin/sh/memalloc.h b/bin/sh/memalloc.h
index 95a659437e66..a22fa3919872 100644
--- a/bin/sh/memalloc.h
+++ b/bin/sh/memalloc.h
@@ -39,7 +39,6 @@ struct stackmark {
struct stack_block *stackp;
char *stacknxt;
int stacknleft;
- struct stackmark *marknext;
};
diff --git a/bin/sh/miscbltin.c b/bin/sh/miscbltin.c
index b81cc822237f..2ecd4f22f27e 100644
--- a/bin/sh/miscbltin.c
+++ b/bin/sh/miscbltin.c
@@ -60,6 +60,7 @@ __FBSDID("$FreeBSD$");
#include "error.h"
#include "mystring.h"
#include "syntax.h"
+#include "trap.h"
#undef eflag
@@ -102,6 +103,8 @@ readcmd(int argc __unused, char **argv __unused)
struct timeval tv;
char *tvptr;
fd_set ifds;
+ ssize_t nread;
+ int sig;
rflag = 0;
prompt = NULL;
@@ -156,8 +159,10 @@ readcmd(int argc __unused, char **argv __unused)
/*
* If there's nothing ready, return an error.
*/
- if (status <= 0)
- return(1);
+ if (status <= 0) {
+ sig = pendingsig;
+ return (128 + (sig != 0 ? sig : SIGALRM));
+ }
}
status = 0;
@@ -165,7 +170,19 @@ readcmd(int argc __unused, char **argv __unused)
backslash = 0;
STARTSTACKSTR(p);
for (;;) {
- if (read(STDIN_FILENO, &c, 1) != 1) {
+ nread = read(STDIN_FILENO, &c, 1);
+ if (nread == -1) {
+ if (errno == EINTR) {
+ sig = pendingsig;
+ if (sig == 0)
+ continue;
+ status = 128 + sig;
+ break;
+ }
+ warning("read error: %s", strerror(errno));
+ status = 2;
+ break;
+ } else if (nread != 1) {
status = 1;
break;
}
diff --git a/bin/sh/mkinit.c b/bin/sh/mkinit.c
deleted file mode 100644
index d73e0e256a73..000000000000
--- a/bin/sh/mkinit.c
+++ /dev/null
@@ -1,480 +0,0 @@
-/*-
- * Copyright (c) 1991, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char const copyright[] =
-"@(#) Copyright (c) 1991, 1993\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)mkinit.c 8.2 (Berkeley) 5/4/95";
-#endif
-#endif /* not lint */
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-/*
- * This program scans all the source files for code to handle various
- * special events and combines this code into one file. This (allegedly)
- * improves the structure of the program since there is no need for
- * anyone outside of a module to know that that module performs special
- * operations on particular events.
- *
- * Usage: mkinit sourcefile...
- */
-
-
-#include <sys/types.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-
-
-/*
- * OUTFILE is the name of the output file. Output is initially written
- * to the file OUTTEMP, which is then moved to OUTFILE.
- */
-
-#define OUTFILE "init.c"
-#define OUTTEMP "init.c.new"
-
-
-/*
- * A text structure is basically just a string that grows as more characters
- * are added onto the end of it. It is implemented as a linked list of
- * blocks of characters. The routines addstr and addchar append a string
- * or a single character, respectively, to a text structure. Writetext
- * writes the contents of a text structure to a file.
- */
-
-#define BLOCKSIZE 512
-
-struct text {
- char *nextc;
- int nleft;
- struct block *start;
- struct block *last;
-};
-
-struct block {
- struct block *next;
- char text[BLOCKSIZE];
-};
-
-
-/*
- * There is one event structure for each event that mkinit handles.
- */
-
-struct event {
- 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 */
-};
-
-
-char writer[] = "\
-/*\n\
- * This file was generated by the mkinit program.\n\
- */\n\
-\n";
-
-char reset[] = "\
-/*\n\
- * This routine is called when an error or an interrupt occurs in an\n\
- * interactive shell and control is returned to the main command loop.\n\
- */\n";
-
-
-struct event event[] = {
- { "RESET", "reset", reset, { NULL, 0, NULL, NULL } },
- { NULL, NULL, NULL, { NULL, 0, NULL, NULL } }
-};
-
-
-const char *curfile; /* current file */
-int linno; /* current line */
-char *header_files[200]; /* list of header files */
-struct text defines; /* #define statements */
-struct text decls; /* declarations */
-int amiddecls; /* for formatting */
-
-
-void readfile(const char *);
-int match(const char *, const char *);
-int gooddefine(const char *);
-void doevent(struct event *, FILE *, const char *);
-void doinclude(char *);
-void dodecl(char *, FILE *);
-void output(void);
-void addstr(const char *, struct text *);
-void addchar(int, struct text *);
-void writetext(struct text *, FILE *);
-FILE *ckfopen(const char *, const char *);
-void *ckmalloc(size_t);
-char *savestr(const char *);
-void error(const char *);
-
-#define equal(s1, s2) (strcmp(s1, s2) == 0)
-
-int
-main(int argc __unused, char *argv[])
-{
- char **ap;
-
- header_files[0] = savestr("\"shell.h\"");
- header_files[1] = savestr("\"mystring.h\"");
- header_files[2] = savestr("\"init.h\"");
- for (ap = argv + 1 ; *ap ; ap++)
- readfile(*ap);
- output();
- rename(OUTTEMP, OUTFILE);
- exit(0);
-}
-
-
-/*
- * Parse an input file.
- */
-
-void
-readfile(const char *fname)
-{
- FILE *fp;
- char line[1024];
- struct event *ep;
-
- fp = ckfopen(fname, "r");
- curfile = fname;
- linno = 0;
- amiddecls = 0;
- while (fgets(line, sizeof line, fp) != NULL) {
- linno++;
- for (ep = event ; ep->name ; ep++) {
- if (line[0] == ep->name[0] && match(ep->name, line)) {
- doevent(ep, fp, fname);
- break;
- }
- }
- if (line[0] == 'I' && match("INCLUDE", line))
- doinclude(line);
- if (line[0] == 'M' && match("MKINIT", line))
- dodecl(line, fp);
- if (line[0] == '#' && gooddefine(line)) {
- char *cp;
- char line2[1024];
- static const char undef[] = "#undef ";
-
- strcpy(line2, line);
- memcpy(line2, undef, sizeof(undef) - 1);
- cp = line2 + sizeof(undef) - 1;
- while(*cp && (*cp == ' ' || *cp == '\t'))
- cp++;
- while(*cp && *cp != ' ' && *cp != '\t' && *cp != '\n')
- cp++;
- *cp++ = '\n'; *cp = '\0';
- addstr(line2, &defines);
- addstr(line, &defines);
- }
- }
- fclose(fp);
-}
-
-
-int
-match(const char *name, const char *line)
-{
- const char *p, *q;
-
- p = name, q = line;
- while (*p) {
- if (*p++ != *q++)
- return 0;
- }
- if (*q != '{' && *q != ' ' && *q != '\t' && *q != '\n')
- return 0;
- return 1;
-}
-
-
-int
-gooddefine(const char *line)
-{
- const char *p;
-
- if (! match("#define", line))
- return 0; /* not a define */
- p = line + 7;
- while (*p == ' ' || *p == '\t')
- p++;
- while (*p != ' ' && *p != '\t') {
- if (*p == '(')
- return 0; /* macro definition */
- p++;
- }
- while (*p != '\n' && *p != '\0')
- p++;
- if (p[-1] == '\\')
- return 0; /* multi-line definition */
- return 1;
-}
-
-
-void
-doevent(struct event *ep, FILE *fp, const char *fname)
-{
- char line[1024];
- int indent;
- const char *p;
-
- sprintf(line, "\n /* from %s: */\n", fname);
- addstr(line, &ep->code);
- addstr(" {\n", &ep->code);
- for (;;) {
- linno++;
- if (fgets(line, sizeof line, fp) == NULL)
- error("Unexpected EOF");
- if (equal(line, "}\n"))
- break;
- indent = 6;
- for (p = line ; *p == '\t' ; p++)
- indent += 8;
- for ( ; *p == ' ' ; p++)
- indent++;
- if (*p == '\n' || *p == '#')
- indent = 0;
- while (indent >= 8) {
- addchar('\t', &ep->code);
- indent -= 8;
- }
- while (indent > 0) {
- addchar(' ', &ep->code);
- indent--;
- }
- addstr(p, &ep->code);
- }
- addstr(" }\n", &ep->code);
-}
-
-
-void
-doinclude(char *line)
-{
- char *p;
- char *name;
- char **pp;
-
- for (p = line ; *p != '"' && *p != '<' && *p != '\0' ; p++);
- if (*p == '\0')
- error("Expecting '\"' or '<'");
- name = p;
- while (*p != ' ' && *p != '\t' && *p != '\n')
- p++;
- if (p[-1] != '"' && p[-1] != '>')
- error("Missing terminator");
- *p = '\0';
-
- /* name now contains the name of the include file */
- for (pp = header_files ; *pp && ! equal(*pp, name) ; pp++);
- if (*pp == NULL)
- *pp = savestr(name);
-}
-
-
-void
-dodecl(char *line1, FILE *fp)
-{
- char line[1024];
- char *p, *q;
-
- if (strcmp(line1, "MKINIT\n") == 0) { /* start of struct/union decl */
- addchar('\n', &decls);
- do {
- linno++;
- if (fgets(line, sizeof line, fp) == NULL)
- error("Unterminated structure declaration");
- addstr(line, &decls);
- } while (line[0] != '}');
- amiddecls = 0;
- } else {
- if (! amiddecls)
- addchar('\n', &decls);
- q = NULL;
- for (p = line1 + 6 ; *p && strchr("=/\n", *p) == NULL; p++)
- continue;
- if (*p == '=') { /* eliminate initialization */
- for (q = p ; *q && *q != ';' ; q++);
- if (*q == '\0')
- q = NULL;
- else {
- while (p[-1] == ' ')
- p--;
- *p = '\0';
- }
- }
- addstr("extern", &decls);
- addstr(line1 + 6, &decls);
- if (q != NULL)
- addstr(q, &decls);
- amiddecls = 1;
- }
-}
-
-
-
-/*
- * Write the output to the file OUTTEMP.
- */
-
-void
-output(void)
-{
- FILE *fp;
- char **pp;
- struct event *ep;
-
- fp = ckfopen(OUTTEMP, "w");
- fputs(writer, fp);
- for (pp = header_files ; *pp ; pp++)
- fprintf(fp, "#include %s\n", *pp);
- fputs("\n\n\n", fp);
- writetext(&defines, fp);
- fputs("\n\n", fp);
- writetext(&decls, fp);
- for (ep = event ; ep->name ; ep++) {
- fputs("\n\n\n", fp);
- fputs(ep->comment, fp);
- fprintf(fp, "\nvoid\n%s(void)\n{\n", ep->routine);
- writetext(&ep->code, fp);
- fprintf(fp, "}\n");
- }
- fclose(fp);
-}
-
-
-/*
- * A text structure is simply a block of text that is kept in memory.
- * Addstr appends a string to the text struct, and addchar appends a single
- * character.
- */
-
-void
-addstr(const char *s, struct text *text)
-{
- while (*s) {
- if (--text->nleft < 0)
- addchar(*s++, text);
- else
- *text->nextc++ = *s++;
- }
-}
-
-
-void
-addchar(int c, struct text *text)
-{
- struct block *bp;
-
- if (--text->nleft < 0) {
- bp = ckmalloc(sizeof *bp);
- if (text->start == NULL)
- text->start = bp;
- else
- text->last->next = bp;
- text->last = bp;
- text->nextc = bp->text;
- text->nleft = BLOCKSIZE - 1;
- }
- *text->nextc++ = c;
-}
-
-/*
- * Write the contents of a text structure to a file.
- */
-void
-writetext(struct text *text, FILE *fp)
-{
- struct block *bp;
-
- if (text->start != NULL) {
- for (bp = text->start ; bp != text->last ; bp = bp->next)
- fwrite(bp->text, sizeof (char), BLOCKSIZE, fp);
- fwrite(bp->text, sizeof (char), BLOCKSIZE - text->nleft, fp);
- }
-}
-
-FILE *
-ckfopen(const char *file, const char *mode)
-{
- FILE *fp;
-
- if ((fp = fopen(file, mode)) == NULL) {
- fprintf(stderr, "Can't open %s: %s\n", file, strerror(errno));
- exit(2);
- }
- return fp;
-}
-
-void *
-ckmalloc(size_t nbytes)
-{
- char *p;
-
- if ((p = malloc(nbytes)) == NULL)
- error("Out of space");
- return p;
-}
-
-char *
-savestr(const char *s)
-{
- char *p;
-
- p = ckmalloc(strlen(s) + 1);
- strcpy(p, s);
- return p;
-}
-
-void
-error(const char *msg)
-{
- if (curfile != NULL)
- fprintf(stderr, "%s:%d: ", curfile, linno);
- fprintf(stderr, "%s\n", msg);
- exit(2);
-}
diff --git a/bin/sh/output.c b/bin/sh/output.c
index d26adce149be..bf8e17d97ece 100644
--- a/bin/sh/output.c
+++ b/bin/sh/output.c
@@ -75,25 +75,6 @@ struct output memout = {NULL, 0, NULL, 0, MEM_OUT, 0};
struct output *out1 = &output;
struct output *out2 = &errout;
-
-
-#ifdef mkinit
-
-INCLUDE "output.h"
-INCLUDE "memalloc.h"
-
-RESET {
- out1 = &output;
- out2 = &errout;
- if (memout.buf != NULL) {
- ckfree(memout.buf);
- memout.buf = NULL;
- }
-}
-
-#endif
-
-
void
outcslow(int c, struct output *file)
{
diff --git a/bin/sh/parser.c b/bin/sh/parser.c
index 073c2b69308f..a0def64c6395 100644
--- a/bin/sh/parser.c
+++ b/bin/sh/parser.c
@@ -96,9 +96,9 @@ static struct heredoc *heredoclist; /* list of here documents to read */
static int doprompt; /* if set, prompt the user */
static int needprompt; /* true if interactive and at start of line */
static int lasttoken; /* last token read */
-MKINIT int tokpushback; /* last token pushed back */
+static int tokpushback; /* last token pushed back */
static char *wordtext; /* text of last word returned by readtoken */
-MKINIT int checkkwd; /* 1 == check for kwds, 2 == also eat newlines */
+static int checkkwd;
static struct nodelist *backquotelist;
static union node *redirnode;
static struct heredoc *heredoc;
@@ -108,12 +108,13 @@ static int funclinno; /* line # where the current function started */
static struct parser_temp *parser_temp;
-static union node *list(int, int);
+static union node *list(int);
static union node *andor(void);
static union node *pipeline(void);
static union node *command(void);
static union node *simplecmd(union node **, union node *);
static union node *makename(void);
+static union node *makebinary(int type, union node *n1, union node *n2);
static void parsefname(void);
static void parseheredoc(void);
static int peektoken(void);
@@ -121,6 +122,7 @@ static int readtoken(void);
static int xxreadtoken(void);
static int readtoken1(int, const char *, const char *, int);
static int noexpand(char *);
+static void consumetoken(int);
static void synexpect(int) __dead2;
static void synerror(const char *) __dead2;
static void setprompt(int);
@@ -210,6 +212,7 @@ parsecmd(int interact)
heredoclist = NULL;
tokpushback = 0;
+ checkkwd = 0;
doprompt = interact;
if (doprompt)
setprompt(1);
@@ -222,18 +225,18 @@ parsecmd(int interact)
if (t == TNL)
return NULL;
tokpushback++;
- return list(1, 1);
+ return list(1);
}
static union node *
-list(int nlflag, int erflag)
+list(int nlflag)
{
union node *ntop, *n1, *n2, *n3;
int tok;
checkkwd = CHKNL | CHKKWD | CHKALIAS;
- if (!nlflag && !erflag && tokendlist[peektoken()])
+ if (!nlflag && tokendlist[peektoken()])
return NULL;
ntop = n1 = NULL;
for (;;) {
@@ -255,17 +258,11 @@ list(int nlflag, int erflag)
if (ntop == NULL)
ntop = n2;
else if (n1 == NULL) {
- n1 = (union node *)stalloc(sizeof (struct nbinary));
- n1->type = NSEMI;
- n1->nbinary.ch1 = ntop;
- n1->nbinary.ch2 = n2;
+ n1 = makebinary(NSEMI, ntop, n2);
ntop = n1;
}
else {
- n3 = (union node *)stalloc(sizeof (struct nbinary));
- n3->type = NSEMI;
- n3->nbinary.ch1 = n1->nbinary.ch2;
- n3->nbinary.ch2 = n2;
+ n3 = makebinary(NSEMI, n1->nbinary.ch2, n2);
n1->nbinary.ch2 = n3;
n1 = n3;
}
@@ -286,8 +283,7 @@ list(int nlflag, int erflag)
tokpushback++;
}
checkkwd = CHKNL | CHKKWD | CHKALIAS;
- if (!nlflag && (erflag ? peektoken() == TEOF :
- tokendlist[peektoken()]))
+ if (!nlflag && tokendlist[peektoken()])
return ntop;
break;
case TEOF:
@@ -297,7 +293,7 @@ list(int nlflag, int erflag)
pungetc(); /* push back EOF on input */
return ntop;
default:
- if (nlflag || erflag)
+ if (nlflag)
synexpect(-1);
tokpushback++;
return ntop;
@@ -310,10 +306,10 @@ list(int nlflag, int erflag)
static union node *
andor(void)
{
- union node *n1, *n2, *n3;
+ union node *n;
int t;
- n1 = pipeline();
+ n = pipeline();
for (;;) {
if ((t = readtoken()) == TAND) {
t = NAND;
@@ -321,14 +317,9 @@ andor(void)
t = NOR;
} else {
tokpushback++;
- return n1;
+ return n;
}
- n2 = pipeline();
- n3 = (union node *)stalloc(sizeof (struct nbinary));
- n3->type = t;
- n3->nbinary.ch1 = n1;
- n3->nbinary.ch2 = n2;
- n1 = n3;
+ n = makebinary(t, n, pipeline());
}
}
@@ -410,49 +401,39 @@ command(void)
case TIF:
n1 = (union node *)stalloc(sizeof (struct nif));
n1->type = NIF;
- if ((n1->nif.test = list(0, 0)) == NULL)
+ if ((n1->nif.test = list(0)) == NULL)
synexpect(-1);
- if (readtoken() != TTHEN)
- synexpect(TTHEN);
- n1->nif.ifpart = list(0, 0);
+ consumetoken(TTHEN);
+ n1->nif.ifpart = list(0);
n2 = n1;
while (readtoken() == TELIF) {
n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif));
n2 = n2->nif.elsepart;
n2->type = NIF;
- if ((n2->nif.test = list(0, 0)) == NULL)
+ if ((n2->nif.test = list(0)) == NULL)
synexpect(-1);
- if (readtoken() != TTHEN)
- synexpect(TTHEN);
- n2->nif.ifpart = list(0, 0);
+ consumetoken(TTHEN);
+ n2->nif.ifpart = list(0);
}
if (lasttoken == TELSE)
- n2->nif.elsepart = list(0, 0);
+ n2->nif.elsepart = list(0);
else {
n2->nif.elsepart = NULL;
tokpushback++;
}
- if (readtoken() != TFI)
- synexpect(TFI);
+ consumetoken(TFI);
checkkwd = CHKKWD | CHKALIAS;
break;
case TWHILE:
- case TUNTIL: {
- int got;
- n1 = (union node *)stalloc(sizeof (struct nbinary));
- n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
- if ((n1->nbinary.ch1 = list(0, 0)) == NULL)
+ case TUNTIL:
+ t = lasttoken;
+ if ((n1 = list(0)) == NULL)
synexpect(-1);
- if ((got=readtoken()) != TDO) {
-TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : ""));
- synexpect(TDO);
- }
- n1->nbinary.ch2 = list(0, 0);
- if (readtoken() != TDONE)
- synexpect(TDONE);
+ consumetoken(TDO);
+ n1 = makebinary((t == TWHILE)? NWHILE : NUNTIL, n1, list(0));
+ consumetoken(TDONE);
checkkwd = CHKKWD | CHKALIAS;
break;
- }
case TFOR:
if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
synerror("Bad for loop variable");
@@ -464,10 +445,7 @@ TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : ""));
if (lasttoken == TWORD && ! quoteflag && equal(wordtext, "in")) {
app = &ap;
while (readtoken() == TWORD) {
- n2 = (union node *)stalloc(sizeof (struct narg));
- n2->type = NARG;
- n2->narg.text = wordtext;
- n2->narg.backquote = backquotelist;
+ n2 = makename();
*app = n2;
app = &n2->narg.next;
}
@@ -499,21 +477,15 @@ TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : ""));
t = TEND;
else
synexpect(-1);
- n1->nfor.body = list(0, 0);
- if (readtoken() != t)
- synexpect(t);
+ n1->nfor.body = list(0);
+ consumetoken(t);
checkkwd = CHKKWD | CHKALIAS;
break;
case TCASE:
n1 = (union node *)stalloc(sizeof (struct ncase));
n1->type = NCASE;
- if (readtoken() != TWORD)
- synexpect(TWORD);
- n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg));
- n2->type = NARG;
- n2->narg.text = wordtext;
- n2->narg.backquote = backquotelist;
- n2->narg.next = NULL;
+ consumetoken(TWORD);
+ n1->ncase.expr = makename();
while (readtoken() == TNL);
if (lasttoken != TWORD || ! equal(wordtext, "in"))
synerror("expecting \"in\"");
@@ -526,10 +498,7 @@ TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : ""));
if (lasttoken == TLP)
readtoken();
for (;;) {
- *app = ap = (union node *)stalloc(sizeof (struct narg));
- ap->type = NARG;
- ap->narg.text = wordtext;
- ap->narg.backquote = backquotelist;
+ *app = ap = makename();
checkkwd = CHKNL | CHKKWD;
if (readtoken() != TPIPE)
break;
@@ -539,7 +508,7 @@ TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : ""));
ap->narg.next = NULL;
if (lasttoken != TRP)
synexpect(TRP);
- cp->nclist.body = list(0, 0);
+ cp->nclist.body = list(0);
checkkwd = CHKNL | CHKKWD | CHKALIAS;
if ((t = readtoken()) != TESAC) {
@@ -559,34 +528,31 @@ TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : ""));
case TLP:
n1 = (union node *)stalloc(sizeof (struct nredir));
n1->type = NSUBSHELL;
- n1->nredir.n = list(0, 0);
+ n1->nredir.n = list(0);
n1->nredir.redirect = NULL;
- if (readtoken() != TRP)
- synexpect(TRP);
+ consumetoken(TRP);
checkkwd = CHKKWD | CHKALIAS;
is_subshell = 1;
break;
case TBEGIN:
- n1 = list(0, 0);
- if (readtoken() != TEND)
- synexpect(TEND);
+ n1 = list(0);
+ consumetoken(TEND);
checkkwd = CHKKWD | CHKALIAS;
break;
- /* Handle an empty command like other simple commands. */
+ /* A simple command must have at least one redirection or word. */
case TBACKGND:
case TSEMI:
case TAND:
case TOR:
- /*
- * An empty command before a ; doesn't make much sense, and
- * should certainly be disallowed in the case of `if ;'.
- */
+ case TPIPE:
+ case TENDCASE:
+ case TFALLTHRU:
+ case TEOF:
+ case TNL:
+ case TRP:
if (!redir)
synexpect(-1);
- case TNL:
- case TEOF:
case TWORD:
- case TRP:
tokpushback++;
n1 = simplecmd(rpp, redir);
return n1;
@@ -644,10 +610,7 @@ simplecmd(union node **rpp, union node *redir)
for (;;) {
checkkwd = savecheckkwd;
if (readtoken() == TWORD) {
- n = (union node *)stalloc(sizeof (struct narg));
- n->type = NARG;
- n->narg.text = wordtext;
- n->narg.backquote = backquotelist;
+ n = makename();
*app = n;
app = &n->narg.next;
if (savecheckkwd != 0 && !isassignment(wordtext))
@@ -659,8 +622,7 @@ simplecmd(union node **rpp, union node *redir)
} else if (lasttoken == TLP && app == &args->narg.next
&& rpp == orig_rpp) {
/* We have a function */
- if (readtoken() != TRP)
- synexpect(TRP);
+ consumetoken(TRP);
funclinno = plinno;
/*
* - Require plain text.
@@ -708,6 +670,18 @@ makename(void)
return n;
}
+static union node *
+makebinary(int type, union node *n1, union node *n2)
+{
+ union node *n;
+
+ n = (union node *)stalloc(sizeof (struct nbinary));
+ n->type = type;
+ n->nbinary.ch1 = n1;
+ n->nbinary.ch2 = n2;
+ return (n);
+}
+
void
fixredir(union node *n, const char *text, int err)
{
@@ -734,8 +708,7 @@ parsefname(void)
{
union node *n = redirnode;
- if (readtoken() != TWORD)
- synexpect(-1);
+ consumetoken(TWORD);
if (n->type == NHERE) {
struct heredoc *here = heredoc;
struct heredoc *p;
@@ -786,11 +759,7 @@ parseheredoc(void)
}
readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
here->eofmark, here->striptabs);
- n = (union node *)stalloc(sizeof (struct narg));
- n->narg.type = NARG;
- n->narg.next = NULL;
- n->narg.text = wordtext;
- n->narg.backquote = backquotelist;
+ n = makename();
here->here->nhere.doc = n;
}
}
@@ -1090,14 +1059,14 @@ done:
doprompt = 0;
}
- n = list(0, oldstyle);
+ n = list(0);
- if (oldstyle)
+ if (oldstyle) {
+ if (peektoken() != TEOF)
+ synexpect(-1);
doprompt = saveprompt;
- else {
- if (readtoken() != TRP)
- synexpect(TRP);
- }
+ } else
+ consumetoken(TRP);
(*nlpp)->n = n;
if (oldstyle) {
@@ -1819,14 +1788,6 @@ parsearith: {
} /* end of readtoken */
-
-#ifdef mkinit
-RESET {
- tokpushback = 0;
- checkkwd = 0;
-}
-#endif
-
/*
* Returns true if the text contains nothing to expand (no dollar signs
* or backquotes).
@@ -1888,6 +1849,14 @@ isassignment(const char *p)
}
+static void
+consumetoken(int token)
+{
+ if (readtoken() != token)
+ synexpect(token);
+}
+
+
/*
* Called when an unexpected token is read during the parse. The argument
* is the token that is expected, or -1 if more than one type of token can
diff --git a/bin/sh/parser.h b/bin/sh/parser.h
index b803f76dbe64..d500d2fd5b8b 100644
--- a/bin/sh/parser.h
+++ b/bin/sh/parser.h
@@ -68,11 +68,9 @@
/*
* NEOF is returned by parsecmd when it encounters an end of file. It
- * must be distinct from NULL, so we use the address of a variable that
- * happens to be handy.
+ * must be distinct from NULL.
*/
-extern int tokpushback;
-#define NEOF ((union node *)&tokpushback)
+#define NEOF ((union node *)-1)
extern int whichprompt; /* 1 == PS1, 2 == PS2 */
extern const char *const parsekwd[];
diff --git a/bin/sh/redir.c b/bin/sh/redir.c
index fda094d27d56..932554578e89 100644
--- a/bin/sh/redir.c
+++ b/bin/sh/redir.c
@@ -66,14 +66,13 @@ __FBSDID("$FreeBSD$");
#define CLOSED -1 /* fd was not open before redir */
-MKINIT
struct redirtab {
struct redirtab *next;
int renamed[10];
};
-MKINIT struct redirtab *redirlist;
+static struct redirtab *redirlist;
/*
* We keep track of whether or not fd0 has been redirected. This is for
@@ -121,7 +120,7 @@ redirect(union node *redir, int flags)
if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) {
INTOFF;
- if ((i = fcntl(fd, F_DUPFD, 10)) == -1) {
+ if ((i = fcntl(fd, F_DUPFD_CLOEXEC, 10)) == -1) {
switch (errno) {
case EBADF:
i = CLOSED;
@@ -131,8 +130,7 @@ redirect(union node *redir, int flags)
error("%d: %s", fd, strerror(errno));
break;
}
- } else
- (void)fcntl(i, F_SETFD, FD_CLOEXEC);
+ }
sv->renamed[fd] = i;
INTON;
}
@@ -321,21 +319,6 @@ popredir(void)
INTON;
}
-/*
- * Undo all redirections. Called on error or interrupt.
- */
-
-#ifdef mkinit
-
-INCLUDE "redir.h"
-
-RESET {
- while (redirlist)
- popredir();
-}
-
-#endif
-
/* Return true if fd 0 has already been redirected at least once. */
int
fd0_redirected_p(void)
diff --git a/bin/sh/sh.1 b/bin/sh/sh.1
index 01cb7756f11d..ea1d899ed8e1 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 March 24, 2013
+.Dd June 14, 2013
.Dt SH 1
.Os
.Sh NAME
@@ -1036,6 +1036,9 @@ The current working directory as set by
The file creation mask as set by
.Ic umask .
.It
+Resource limits as set by
+.Ic ulimit .
+.It
References to open files.
.It
Traps as set by
@@ -1142,8 +1145,10 @@ command is
.Pp
.D1 Ic return Op Ar exitstatus
.Pp
-It terminates the current executional scope, returning from the previous
-nested function, sourced script, or shell instance, in that order.
+It terminates the current executional scope, returning from the closest
+nested function or sourced script;
+if no function or sourced script is being executed,
+it exits the shell instance.
The
.Ic return
command is implemented as a special built-in command.
@@ -1340,9 +1345,33 @@ The primary prompt string, which defaults to
.Dq Li "$ " ,
unless you are the superuser, in which case it defaults to
.Dq Li "# " .
+.Va PS1
+may include any of the following formatting sequences,
+which are replaced by the given information:
+.Bl -tag -width indent
+.It Li \eH
+The local hostname.
+.It Li \eh
+The fully-qualified hostname.
+.It Li \eW
+The final component of the current working directory.
+.It Li \ew
+The entire path of the current working directory.
+.It Li \e$
+Superuser status.
+.Dq Li "$ "
+for normal users and
+.Dq Li "# "
+for superusers.
+.It Li \e\e
+A literal backslash.
+.El
.It Va PS2
The secondary prompt string, which defaults to
.Dq Li "> " .
+.Va PS2
+may include any of the formatting sequences from
+.Va PS1 .
.It Va PS4
The prefix for the trace output (if
.Fl x
@@ -2348,7 +2377,9 @@ option is specified and the
elapses before a complete line of input is supplied,
the
.Ic read
-command will return an exit status of 1 without assigning any values.
+command will return an exit status as if terminated by
+.Dv SIGALRM
+without assigning any values.
The
.Ar timeout
value may optionally be followed by one of
@@ -2364,6 +2395,11 @@ is assumed.
The
.Fl e
option exists only for backward compatibility with older scripts.
+.Pp
+The exit status is 0 on success, 1 on end of file,
+between 2 and 128 if an error occurs
+and greater than 128 if a trapped signal interrupts
+.Ic read .
.It Ic readonly Oo Fl p Oc Op Ar name ...
Each specified
.Ar name
@@ -2611,12 +2647,17 @@ If the
option is specified, the
.Ar name
arguments are treated as function names.
-.It Ic wait Op Ar job
-Wait for the specified
+.It Ic wait Op Ar job ...
+Wait for each specified
.Ar job
to complete and return the exit status of the last process in the
+last specified
.Ar job .
-If the argument is omitted, wait for all jobs to complete
+If any
+.Ar job
+specified is unknown to the shell, it is treated as if it
+were a known job that exited with exit status 127.
+If no operands are given, wait for all jobs to complete
and return an exit status of zero.
.El
.Ss Commandline Editing
diff --git a/bin/sh/shell.h b/bin/sh/shell.h
index 5f6d0ac68ab5..679efc7b1619 100644
--- a/bin/sh/shell.h
+++ b/bin/sh/shell.h
@@ -63,7 +63,6 @@ typedef intmax_t arith_t;
#define ARITH_MAX INTMAX_MAX
typedef void *pointer;
-#define MKINIT /* empty */
#include <sys/cdefs.h>
diff --git a/bin/sh/trap.c b/bin/sh/trap.c
index 313802925592..3fc85668c642 100644
--- a/bin/sh/trap.c
+++ b/bin/sh/trap.c
@@ -72,8 +72,9 @@ __FBSDID("$FreeBSD$");
#define S_RESET 5 /* temporary - to reset a hard ignored sig */
-MKINIT char sigmode[NSIG]; /* current value of signal */
+static char sigmode[NSIG]; /* current value of signal */
volatile sig_atomic_t pendingsig; /* indicates some signal received */
+volatile sig_atomic_t pendingsig_waitcmd; /* indicates SIGINT/SIGQUIT 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];
@@ -389,23 +390,13 @@ onsig(int signo)
}
/* If we are currently in a wait builtin, prepare to break it */
- if ((signo == SIGINT || signo == SIGQUIT) && in_waitcmd != 0) {
- breakwaitcmd = 1;
- pendingsig = signo;
- }
+ if (signo == SIGINT || signo == SIGQUIT)
+ pendingsig_waitcmd = 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
@@ -428,6 +419,7 @@ dotrap(void)
in_dotrap++;
for (;;) {
pendingsig = 0;
+ pendingsig_waitcmd = 0;
for (i = 1; i < NSIG; i++) {
if (gotsig[i]) {
gotsig[i] = 0;
diff --git a/bin/sh/trap.h b/bin/sh/trap.h
index 0a05d8d0ad21..a9622514c0b4 100644
--- a/bin/sh/trap.h
+++ b/bin/sh/trap.h
@@ -34,6 +34,7 @@
*/
extern volatile sig_atomic_t pendingsig;
+extern volatile sig_atomic_t pendingsig_waitcmd;
extern int in_dotrap;
extern volatile sig_atomic_t gotwinch;
diff --git a/bin/sh/var.c b/bin/sh/var.c
index 3f29a48ed057..c20d03263708 100644
--- a/bin/sh/var.c
+++ b/bin/sh/var.c
@@ -710,6 +710,7 @@ localcmd(int argc __unused, char **argv __unused)
{
char *name;
+ nextopt("");
if (! in_function())
error("Not in a function");
while ((name = *argptr++) != NULL) {
@@ -877,7 +878,7 @@ unsetvar(const char *s)
/*
- * Returns true if the two strings specify the same varable. The first
+ * Returns true if the two strings specify the same variable. The first
* variable name is terminated by '='; the second may be terminated by
* either '=' or '\0'.
*/
@@ -898,7 +899,7 @@ varequal(const char *p, const char *q)
* Search for a variable.
* 'name' may be terminated by '=' or a NUL.
* vppp is set to the pointer to vp, or the list head if vp isn't found
- * lenp is set to the number of charactets in 'name'
+ * lenp is set to the number of characters in 'name'
*/
static struct var *
diff --git a/bin/sleep/sleep.c b/bin/sleep/sleep.c
index fa7deb2f5ca5..ca082723fbe1 100644
--- a/bin/sleep/sleep.c
+++ b/bin/sleep/sleep.c
@@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$");
#include <ctype.h>
#include <err.h>
+#include <errno.h>
#include <limits.h>
#include <signal.h>
#include <stdint.h>
@@ -81,14 +82,20 @@ main(int argc, char *argv[])
time_to_sleep.tv_nsec = 1e9 * (d - time_to_sleep.tv_sec);
signal(SIGINFO, report_request);
+
+ /*
+ * Note: [EINTR] is supposed to happen only when a signal was handled
+ * but the kernel also returns it when a ptrace-based debugger
+ * attaches. This is a bug but it is hard to fix.
+ */
while (nanosleep(&time_to_sleep, &time_to_sleep) != 0) {
if (report_requested) {
/* Reporting does not bother with nanoseconds. */
warnx("about %d second(s) left out of the original %d",
(int)time_to_sleep.tv_sec, (int)original);
report_requested = 0;
- } else
- break;
+ } else if (errno != EINTR)
+ err(1, "nanosleep");
}
return (0);
}
diff --git a/bin/test/test.1 b/bin/test/test.1
index 76a4a9cb2607..136ee5724fdf 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 December 27, 2012
+.Dd June 1, 2013
.Dt TEST 1
.Os
.Sh NAME
@@ -169,65 +169,15 @@ True if
.Ar file
exists and is a socket.
.It Ar file1 Fl nt Ar file2
-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
+True if
.Ar file1
-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
+exists and is newer than
.Ar file2 .
-Note that
-.Ic -ntmm
-is equivalent to
-.Ic -nt .
.It Ar file1 Fl ot Ar file2
-True if both
-.Ar file1
-and
-.Ar file2
-exist and
+True if
.Ar file1
-is older than
+exists and 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
@@ -381,6 +331,20 @@ missing.
.It >1
An error occurred.
.El
+.Sh EXAMPLES
+Implement
+.Li test FILE1 -nt FILE2
+using only
+.Tn POSIX
+functionality:
+.Pp
+.Dl test -n \&"$(find -L -- FILE1 -prune -newer FILE2 2>/dev/null)\&"
+.Pp
+This can be modified using non-standard
+.Xr find 1
+primaries like
+.Cm -newerca
+to compare other timestamps.
.Sh COMPATIBILITY
For compatibility with some other implementations,
the
@@ -391,7 +355,9 @@ with the same meaning.
.Sh SEE ALSO
.Xr builtin 1 ,
.Xr expr 1 ,
+.Xr find 1 ,
.Xr sh 1 ,
+.Xr stat 1 ,
.Xr symlink 7
.Sh STANDARDS
The
@@ -399,6 +365,17 @@ The
utility implements a superset of the
.St -p1003.2
specification.
+The primaries
+.Cm < ,
+.Cm == ,
+.Cm > ,
+.Fl ef ,
+.Fl nt ,
+.Fl ot ,
+.Fl G ,
+and
+.Fl O
+are extensions.
.Sh BUGS
Both sides are always evaluated in
.Fl a
diff --git a/bin/test/test.c b/bin/test/test.c
index eaa2f4034446..96aa9f54970f 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"|"-nt[abcm][abcm]"|"-ot"|"-ot[abcm][abcm])"|"-ef";
+ "-nt"|"-ot"|"-ef";
operand ::= <any legal UNIX file name>
*/
@@ -85,38 +85,8 @@ enum token {
FILSUID,
FILSGID,
FILSTCK,
- 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,
+ FILNT,
+ FILOT,
FILEQ,
FILUID,
FILGID,
@@ -148,16 +118,9 @@ enum token_types {
PAREN
};
-enum time_types {
- ATIME,
- BTIME,
- CTIME,
- MTIME
-};
-
static struct t_op {
- char op_text[6];
- char op_num, op_type;
+ char op_text[4];
+ short op_num, op_type;
} const ops [] = {
{"-r", FILRD, UNOP},
{"-w", FILWR, UNOP},
@@ -191,40 +154,8 @@ static struct t_op {
{"-gt", INTGT, BINOP},
{"-le", INTLE, BINOP},
{"-lt", INTLT, 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},
+ {"-nt", FILNT, BINOP},
+ {"-ot", FILOT, BINOP},
{"-ef", FILEQ, BINOP},
{"!", UNOT, BUNOP},
{"-a", BAND, BBINOP},
@@ -249,10 +180,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 *, enum time_types,
- enum time_types);
+static int newerf(const char *, const char *);
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 *);
@@ -422,70 +353,10 @@ binop(void)
return intcmp(opnd1, opnd2) <= 0;
case INTLT:
return intcmp(opnd1, opnd2) < 0;
- 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 FILNT:
+ return newerf (opnd1, opnd2);
+ case FILOT:
+ return olderf (opnd1, opnd2);
case FILEQ:
return equalf (opnd1, opnd2);
default:
@@ -699,34 +570,25 @@ intcmp (const char *s1, const char *s2)
}
static int
-newerf (const char *f1, const char *f2, enum time_types t1, enum time_types t2)
+newerf (const char *f1, const char *f2)
{
struct stat b1, b2;
- struct timespec *ts1, *ts2;
if (stat(f1, &b1) != 0 || stat(f2, &b2) != 0)
return 0;
- 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)
+ if (b1.st_mtim.tv_sec > b2.st_mtim.tv_sec)
return 1;
- if (ts1->tv_sec < ts2->tv_sec)
+ if (b1.st_mtim.tv_sec < b2.st_mtim.tv_sec)
return 0;
- return (ts1->tv_nsec > ts2->tv_nsec);
+ return (b1.st_mtim.tv_nsec > b2.st_mtim.tv_nsec);
+}
+
+static int
+olderf (const char *f1, const char *f2)
+{
+ return (newerf(f2, f1));
}
static int