stargazing/cosmo/unbourne-backports.patch

1671 lines
57 KiB
Diff

--- a/examples/unbourne.c
+++ b/examples/unbourne.c
@@ -59,8 +59,8 @@
for decades thanks to a spark of brilliance from Ken Thompson.
git://git.kernel.org/pub/scm/utils/dash/dash.git
- fba95e9e4a5d0f1f1ac9f7d86557e47bc0e2656c
- Tue Jun 19 11:27:37 2018 -0400
+ 057cd650a4edd5856213d431a974ff35c6594489
+ Fri Sep 03 15:00:58 2021 +0800
The UNBOURNE SHELL pays HOMAGE to the Stewards of House California:
@@ -68,7 +68,7 @@
Derived from software contributed to Berkeley by Kenneth Almquist.
Copyright 1991,1993 The Regents of the University of California
- Copyright 1997-2018 Herbert Xu
+ Copyright 1997-2021 Herbert Xu
Copyright 1997 Christos Zoulas
Redistribution and use in source and binary forms, with or without
@@ -183,6 +183,7 @@
/* exceptions */
#define EXINT 0
#define EXERROR 1
+#define EXEND 3
#define EXEXIT 4
/*
@@ -207,7 +208,6 @@
#define CEOF 11
#define CCTL 12
#define CSPCL 13
-#define CIGN 14
/* Syntax classes for is_ functions */
#define ISDIGIT 01
@@ -216,13 +216,11 @@
#define ISUNDER 010
#define ISSPECL 020
-#define SYNBASE 130
-#define PEOF -130
+#define SYNBASE 129
+#define PEOF -129
#define EOF_NLEFT -99
-#define PEOA -129
-
#define BASESYNTAX (basesyntax + SYNBASE)
#define DQSYNTAX (dqsyntax + SYNBASE)
#define SQSYNTAX (sqsyntax + SYNBASE)
@@ -345,6 +343,7 @@
#define VSTRIMLEFT 0x8
#define VSTRIMLEFTMAX 0x9
#define VSLENGTH 0xa
+/* VSLENGTH must come last. */
/* values of checkkwd variable */
#define CHKALIAS 0x1
@@ -484,9 +483,10 @@
#define CUR_STOPPED 0
/* mode flags for dowait */
-#define DOWAIT_NORMAL 0
-#define DOWAIT_BLOCK 1
-#define DOWAIT_WAITCMD 2
+#define DOWAIT_NONBLOCK 0
+#define DOWAIT_BLOCK 1
+#define DOWAIT_WAITCMD 2
+#define DOWAIT_WAITCMD_ALL 4
/* _rmescape() flags */
#define RMESCAPE_ALLOC 0x01
@@ -570,7 +570,6 @@
#define CD_PHYSICAL 1
#define CD_PRINT 2
-#define REALLY_CLOSED -3
#define EMPTY -2
#define CLOSED -1
#define PIPESIZE 4096
@@ -711,10 +710,11 @@
struct strpush *prev; /* preceding string on stack */
char *prevstring;
int prevnleft;
- struct alias *ap; /* if push was associated with an alias */
- char *string; /* remember the string since it may change */
- int lastc[2]; /* Remember last two characters for pungetc. */
- int unget; /* Number of outstanding calls to pungetc. */
+ struct alias *ap; /* if push was associated with an alias */
+ char *string; /* remember the string since it may change */
+ struct strpush *spfree; /* Delay freeing so we can stop nested aliases. */
+ int lastc[2]; /* Remember last two characters for pungetc. */
+ int unget; /* Number of outstanding calls to pungetc. */
};
/*
@@ -731,6 +731,7 @@
char *buf; /* input buffer */
struct strpush *strpush; /* for pushing strings at this level */
struct strpush basestrpush; /* so pushing one is fast */
+ struct strpush *spfree; /* Delay freeing so we can stop nested aliases. */
int lastc[2]; /* Remember last two characters for pungetc. */
int unget; /* Number of outstanding calls to pungetc. */
};
@@ -1055,8 +1056,8 @@
static int funcblocksize; /* size of structures in function */
static int funcline; /* start line of function, or 0 if not in one */
static int funcstringsize; /* size of strings in node */
-static int gotsigchld; /* received SIGCHLD */
static int initialpgrp; /* pgrp of shell on invocation */
+static int inps4; /* Prevent PS4 nesting. */
static int job_warning;
static int jobctl;
static int last_token;
@@ -1083,6 +1084,7 @@
static struct ifsregion *ifslastp; /* last struct in list */
static struct ifsregion ifsfirst; /* first struct in list of ifs regions */
static struct jmploc *handler;
+static struct jmploc main_handler;
static struct job *curjob; /* current job */
static struct job *jobtab; /* array of jobs */
static struct localvar_list *localvar_stack;
@@ -1099,8 +1101,10 @@
static struct Var *vartab[VTABSIZE];
static union node *redirnode;
static union yystype yylval;
+static unsigned closed_redirs; /* Bit map of currently closed file descriptors. */
static unsigned expdir_max;
static unsigned njobs; /* size of array */
+static volatile sig_atomic_t gotsigchld; /* received SIGCHLD */
static volatile sig_atomic_t intpending;
static volatile sig_atomic_t pending_sig; /* last pending signal */
static struct alias *atab[ATABSIZE];
@@ -1217,117 +1221,135 @@
/* syntax table used when not in quotes */
static const char basesyntax[] /* clang-format off */ = {
- CEOF, CSPCL, CWORD, CCTL, CCTL, CCTL, CCTL, CCTL, CCTL,
- CCTL, CCTL, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CSPCL, CNL, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CSPCL, CWORD, CDQUOTE, CWORD, CVAR, CWORD, CSPCL, CSQUOTE, CSPCL,
- CSPCL, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CSPCL, CSPCL, CWORD, CSPCL, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CBACK, CWORD, CWORD,
- CWORD, CBQUOTE, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CSPCL, CENDVAR, CWORD, CWORD
+ CEOF, CWORD, CCTL, CCTL, CCTL, CCTL, CCTL, CCTL, CCTL,
+ CCTL, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CSPCL, CNL, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CSPCL,
+ CWORD, CDQUOTE, CWORD, CVAR, CWORD, CSPCL, CSQUOTE, CSPCL, CSPCL,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CSPCL,
+ CSPCL, CWORD, CSPCL, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CBACK, CWORD, CWORD, CWORD,
+ CBQUOTE, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CSPCL, CENDVAR, CWORD, CWORD
} /* clang-format on */;
/* syntax table used when in double quotes */
static const char dqsyntax[] /* clang-format off */ = {
- CEOF, CIGN, CWORD, CCTL, CCTL, CCTL, CCTL, CCTL, CCTL,
- CCTL, CCTL, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CNL, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CCTL, CENDQUOTE, CWORD, CVAR, CWORD, CWORD, CWORD, CWORD,
- CWORD, CCTL, CWORD, CWORD, CCTL, CWORD, CCTL, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CCTL,
- CWORD, CWORD, CCTL, CWORD, CCTL, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CCTL, CBACK, CCTL, CWORD,
- CWORD, CBQUOTE, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CENDVAR, CCTL, CWORD
+ CEOF, CWORD, CCTL, CCTL, CCTL, CCTL, CCTL, CCTL, CCTL,
+ CCTL, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CNL, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CCTL, CENDQUOTE, CWORD, CVAR, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CCTL, CWORD, CWORD, CCTL, CWORD, CCTL, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CCTL, CWORD,
+ CWORD, CCTL, CWORD, CCTL, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CCTL, CBACK, CCTL, CWORD, CWORD,
+ CBQUOTE, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CENDVAR, CCTL, CWORD
} /* clang-format on */;
/* syntax table used when in single quotes */
-static const char sqsyntax[] = {
- CEOF, CIGN, CWORD, CCTL, CCTL, CCTL, CCTL, CCTL, CCTL, CCTL, CCTL, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CNL, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CCTL, CWORD, CWORD, CWORD, CWORD, CWORD,
- CENDQUOTE, CWORD, CWORD, CCTL, CWORD, CWORD, CCTL, CWORD, CCTL, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CCTL, CWORD, CWORD, CCTL, CWORD, CCTL, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CCTL, CCTL, CCTL, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CCTL, CWORD,
-};
+static const char sqsyntax[] /* clang-format off */ = {
+ CEOF, CWORD, CCTL, CCTL, CCTL, CCTL, CCTL, CCTL, CCTL,
+ CCTL, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CNL, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CCTL, CWORD, CWORD, CWORD, CWORD, CWORD, CENDQUOTE, CWORD, CWORD,
+ CCTL, CWORD, CWORD, CCTL, CWORD, CCTL, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CCTL, CWORD,
+ CWORD, CCTL, CWORD, CCTL, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CCTL, CCTL, CCTL, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CCTL, CWORD
+} /* clang-format on */;
/* syntax table used when in arithmetic */
-static const char arisyntax[] = {
- CEOF, CIGN, CWORD, CCTL, CCTL, CCTL, CCTL, CCTL, CCTL, CCTL, CCTL, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CNL, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CVAR, CWORD, CWORD,
- CWORD, CLP, CRP, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CBACK, CWORD, CWORD, CWORD, CBQUOTE, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
- CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CENDVAR, CWORD, CWORD,
-};
+static const char arisyntax[] /* clang-format off */ = {
+ CEOF, CWORD, CCTL, CCTL, CCTL, CCTL, CCTL, CCTL, CCTL,
+ CCTL, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CNL, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CVAR, CWORD, CWORD, CWORD, CLP, CRP,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CBACK, CWORD, CWORD, CWORD,
+ CBQUOTE, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD, CWORD,
+ CWORD, CWORD, CENDVAR, CWORD, CWORD
+} /* clang-format on */;
/* character classification table */
static const char is_type[] /* clang-format off */ = {
@@ -1351,19 +1373,19 @@
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, ISSPECL, 0, ISSPECL, ISSPECL, 0,
- 0, 0, 0, 0, ISSPECL, 0, 0, ISSPECL,
- 0, 0, ISDIGIT, ISDIGIT, ISDIGIT, ISDIGIT, ISDIGIT, ISDIGIT,
- ISDIGIT, ISDIGIT, ISDIGIT, ISDIGIT, 0, 0, 0, 0,
- 0, ISSPECL, ISSPECL, ISUPPER, ISUPPER, ISUPPER, ISUPPER, ISUPPER,
+ 0, 0, ISSPECL, 0, ISSPECL, ISSPECL, 0, 0,
+ 0, 0, 0, ISSPECL, 0, 0, ISSPECL, 0,
+ 0, ISDIGIT, ISDIGIT, ISDIGIT, ISDIGIT, ISDIGIT, ISDIGIT, ISDIGIT,
+ ISDIGIT, ISDIGIT, ISDIGIT, 0, 0, 0, 0, 0,
+ ISSPECL, ISSPECL, ISUPPER, ISUPPER, ISUPPER, ISUPPER, ISUPPER, ISUPPER,
ISUPPER, ISUPPER, ISUPPER, ISUPPER, ISUPPER, ISUPPER, ISUPPER, ISUPPER,
ISUPPER, ISUPPER, ISUPPER, ISUPPER, ISUPPER, ISUPPER, ISUPPER, ISUPPER,
- ISUPPER, ISUPPER, ISUPPER, ISUPPER, ISUPPER, 0, 0, 0,
- 0, ISUNDER, 0, ISLOWER, ISLOWER, ISLOWER, ISLOWER, ISLOWER,
+ ISUPPER, ISUPPER, ISUPPER, ISUPPER, 0, 0, 0, 0,
+ ISUNDER, 0, ISLOWER, ISLOWER, ISLOWER, ISLOWER, ISLOWER, ISLOWER,
ISLOWER, ISLOWER, ISLOWER, ISLOWER, ISLOWER, ISLOWER, ISLOWER, ISLOWER,
ISLOWER, ISLOWER, ISLOWER, ISLOWER, ISLOWER, ISLOWER, ISLOWER, ISLOWER,
- ISLOWER, ISLOWER, ISLOWER, ISLOWER, ISLOWER, 0, 0, 0,
- 0, 0
+ ISLOWER, ISLOWER, ISLOWER, ISLOWER, 0, 0, 0, 0,
+ 0
} /* clang-format on */;
static int aliascmd();
@@ -2141,9 +2163,7 @@
static int options(int);
static int padvance_magic(const char **, const char *, int);
static int patmatch(char *, const char *);
-static int peektoken(void);
static int pgetc(void);
-static int pgetc2(void);
static int pgetc_eatbnl();
static int pmatch(const char *, const char *);
static int preadbuffer(void);
@@ -2155,6 +2175,7 @@
static int redirectsafe(union node *, int);
static int savefd(int, int);
static int setinputfile(const char *, int);
+static int sh_open(const char *pathname, int flags, int mayfail);
static int showvars(const char *, int, int);
static int stoppedjobs(void);
static int test_file_access(const char *, int);
@@ -2195,21 +2216,20 @@
static void addcmdentry(char *, struct cmdentry *);
static void addfname(char *);
static void check_conversion(const char *, const char *);
-static void clear_traps(void);
static void clearcmdentry(void);
-static void closescript(void);
static void defun(union node *);
static void delete_cmd_entry(void);
static void dotrap(void);
static void dupredirect(union node *, int);
static void exitreset(void);
static void expandarg(union node *arg, struct arglist *arglist, int flag);
-static void expandmeta(struct strlist *, int);
+static void expandmeta(struct strlist *);
static void expbackq(union node *, int);
static void expmeta(char *, unsigned, unsigned);
static void expredir(union node *);
static void find_command(char *, struct cmdentry *, int, const char *);
static void fixredir(union node *, const char *, int);
+static void forkreset(void);
static void freeparam(volatile struct shparam *);
static void hashcd(void);
static void ignoresig(int);
@@ -2222,7 +2242,7 @@
static void parseheredoc(void);
static void popallfiles(void);
static void popfile(void);
-static void poplocalvars(int);
+static void poplocalvars(void);
static void popredir(int);
static void popstring(void);
static void prehash(union node *);
@@ -3083,8 +3103,11 @@
static int evaltree(union node *n, int flags) {
int checkexit = 0;
int (*evalfn)(union node *, int);
+ struct stackmark smark;
unsigned isor;
int status = 0;
+ setstackmark(&smark);
+ if (nflag) goto out;
if (n == NULL) {
TRACE(("evaltree(NULL) called\n"));
goto out;
@@ -3108,7 +3131,7 @@
case NCMD:
evalfn = evalcommand;
checkexit:
- if (eflag && !(flags & EV_TESTED)) checkexit = ~0;
+ checkexit = ~flags & EV_TESTED;
goto calleval;
case NFOR:
evalfn = evalfor;
@@ -3132,8 +3155,6 @@
case NSEMI:
isor = n->type - NAND;
status = evaltree(n->nbinary.ch1, (flags | ((isor >> 1) - 1)) & EV_TESTED);
- /* XXX: -Wlogical-not-parentheses:
- if (!status == isor || evalskip) break; */
if ((!status) == isor || evalskip) break;
n = n->nbinary.ch2;
evaln:
@@ -3160,12 +3181,13 @@
break;
}
out:
- if (checkexit & status) goto exexit;
dotrap();
+ if (eflag && checkexit & status) goto exexit;
if (flags & EV_EXIT) {
exexit:
- exraise(EXEXIT);
+ exraise(EXEND);
}
+ popstackmark(&smark);
return exitstatus;
}
@@ -3261,11 +3283,9 @@
struct arglist arglist;
union node *argp;
struct strlist *sp;
- struct stackmark smark;
int status;
errlinno = lineno = n->nfor.linno;
if (funcline) lineno -= funcline - 1;
- setstackmark(&smark);
arglist.lastp = &arglist.list;
for (argp = n->nfor.args; argp; argp = argp->narg.next) {
expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
@@ -3280,7 +3300,6 @@
if (skiploop() & ~SKIPCONT) break;
}
loopnest--;
- popstackmark(&smark);
return status;
}
@@ -3304,11 +3323,9 @@
union node *cp;
union node *patp;
struct arglist arglist;
- struct stackmark smark;
int status = 0;
errlinno = lineno = n->ncase.linno;
if (funcline) lineno -= funcline - 1;
- setstackmark(&smark);
arglist.lastp = &arglist.list;
expandarg(n->ncase.expr, &arglist, EXP_TILDE);
for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
@@ -3326,7 +3343,6 @@
}
}
out:
- popstackmark(&smark);
return status;
}
@@ -3340,14 +3356,17 @@
errlinno = lineno = n->nredir.linno;
if (funcline) lineno -= funcline - 1;
expredir(n->nredir.redirect);
- if (!backgnd && flags & EV_EXIT && !have_traps()) goto nofork;
INTOFF;
+ if (!backgnd && flags & EV_EXIT && !have_traps()) {
+ forkreset();
+ goto nofork;
+ }
jp = makejob(n, 1);
if (forkshell(jp, n, backgnd) == 0) {
- INTON;
flags |= EV_EXIT;
if (backgnd) flags &= ~EV_TESTED;
nofork:
+ INTON;
redirect(n->nredir.redirect, 0);
evaltreenr(n->nredir.n, flags);
/* never returns */
@@ -3378,7 +3397,7 @@
case NFROMFD:
case NTOFD:
if (redir->ndup.vname) {
- expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
+ expandarg(redir->ndup.vname, &fn, EXP_TILDE | EXP_REDIR);
fixredir(redir, fn.list->text, 1);
}
break;
@@ -3527,7 +3546,6 @@
struct localvar_list *localvar_stop;
struct parsefile *file_stop;
struct redirtab *redir_stop;
- struct stackmark smark;
union node *argp;
struct arglist arglist;
struct arglist varlist;
@@ -3550,7 +3568,6 @@
if (funcline) lineno -= funcline - 1;
/* First expand the arguments. */
TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
- setstackmark(&smark);
file_stop = parsefile;
back_exitstatus = 0;
cmdentry.cmdtype = CMDBUILTIN;
@@ -3624,11 +3641,13 @@
setvareq((*spp)->text, vflags);
}
/* Print the command if xflag is set. */
- if (xflag) {
+ if (xflag && !inps4) {
struct output *out;
int sep;
out = &preverrout;
+ inps4 = 1;
outstr(expandstr(ps4val()), out);
+ inps4 = 0;
sep = 0;
sep = eprintlist(out, varlist.list, sep);
eprintlist(out, osp, sep);
@@ -3679,7 +3698,6 @@
*/
setvar("_", lastarg, 0);
}
- popstackmark(&smark);
return status;
}
@@ -3702,6 +3720,7 @@
else
status = (*cmd->builtin)(argc, argv);
flushall();
+ if (out1->flags) sh_warnx("%s: I/O error", commandname);
status |= out1->flags;
exitstatus = status;
cmddone:
@@ -3893,7 +3912,7 @@
exerrno = (e == ELOOP || e == ENAMETOOLONG || e == ENOENT || e == ENOTDIR) ? 127 : 126;
exitstatus = exerrno;
TRACE(("shellexec failed for %s, errno %d, suppressint %d\n", argv[0], e, suppressint));
- exerror(EXEXIT, "%s: %s", argv[0], errmsg(e, E_EXEC));
+ exerror(EXEND, "%s: %s", argv[0], errmsg(e, E_EXEC));
}
static void tryexec(char *cmd, char **argv, char **envp) {
@@ -4498,7 +4517,7 @@
ifsbreakup(p, -1, &exparg);
*exparg.lastp = NULL;
exparg.lastp = &exparg.list;
- expandmeta(exparg.list, flag);
+ expandmeta(exparg.list);
} else {
sp = (struct strlist *)stalloc(sizeof(struct strlist));
sp->text = p;
@@ -4560,7 +4579,7 @@
q = stnputs(p, length, expdest);
q[-1] &= end - 1;
expdest = q - (flag & EXP_WORD ? end : 0);
- newloc = expdest - (char *)stackblock() - end;
+ newloc = q - (char *)stackblock() - end;
if (breakall && !inquotes && newloc > startloc) {
recordregion(startloc, newloc, 0);
}
@@ -4756,7 +4775,7 @@
INTON;
/* Eat all trailing newlines */
dest = expdest;
- for (; dest > (char *)stackblock() && dest[-1] == '\n';) {
+ for (; dest > ((char *)stackblock() + startloc) && dest[-1] == '\n';) {
STUNPUTC(dest);
}
expdest = dest;
@@ -4889,6 +4908,7 @@
int patloc;
int startloc;
long varlen;
+ int discard;
int quoted;
varflags = *p++;
subtype = varflags & VSTYPE;
@@ -4899,31 +4919,32 @@
again:
varlen = varvalue(var_, varflags, flag, quoted);
if (varflags & VSNUL) varlen--;
+ discard = varlen < 0 ? EXP_DISCARD : 0;
switch (subtype) {
case VSPLUS:
- varlen = -1 - varlen;
+ discard ^= EXP_DISCARD;
/* fall through */
case 0:
case VSMINUS:
- p = argstr(p, flag | EXP_TILDE | EXP_WORD);
- if (varlen < 0) return p;
+ p = argstr(p, flag | EXP_TILDE | EXP_WORD | (discard ^ EXP_DISCARD));
goto record;
case VSASSIGN:
case VSQUESTION:
- if (varlen >= 0) goto record;
- p = subevalvar(p, var_, 0, startloc, varflags, flag & ~QUOTES_ESC);
- if (flag & EXP_DISCARD) return p;
+ p = subevalvar(p, var_, 0, startloc, varflags, (flag & ~QUOTES_ESC) | (discard ^ EXP_DISCARD));
+ if ((flag | ~discard) & EXP_DISCARD) goto record;
varflags &= ~VSNUL;
+ subtype = VSNORMAL;
goto again;
}
- if (varlen < 0 && uflag) varunset(p, var_, 0, 0);
+ if ((discard & ~flag) && uflag) varunset(p, var_, 0, 0);
if (subtype == VSLENGTH) {
+ p++;
if (flag & EXP_DISCARD) return p;
cvtnum(varlen > 0 ? varlen : 0, flag);
- goto record;
+ goto really_record;
}
if (subtype == VSNORMAL) goto record;
- flag |= varlen < 0 ? EXP_DISCARD : 0;
+ flag |= discard;
if (!(flag & EXP_DISCARD)) {
/*
* Terminate the string and start recording the pattern
@@ -4934,7 +4955,8 @@
patloc = expdest - (char *)stackblock();
p = subevalvar(p, NULL, patloc, startloc, varflags, flag);
record:
- if (flag & EXP_DISCARD) return p;
+ if ((flag | discard) & EXP_DISCARD) return p;
+really_record:
if (quoted) {
quoted = *var_ == '@' && shellparam.nparam;
if (!quoted) return p;
@@ -5212,7 +5234,7 @@
* Expand shell metacharacters. At this point, the only control characters
* should be escapes. The results are stored in the list exparg.
*/
-static void expandmeta(struct strlist *str, int flag) {
+static void expandmeta(struct strlist *str) {
static const char metachars[] = {'*', '?', '[', 0};
/* TODO - EXP_REDIR */
while (str) {
@@ -5595,11 +5617,23 @@
return memtodest(buf, len, flags);
}
-/*
- * Read a character from the script, returning PEOF on end of file.
- * Nul characters in the input are silently discarded.
- */
-static int pgetc(void) {
+static void freestrings(struct strpush *sp) {
+ INTOFF;
+ do {
+ struct strpush *psp;
+ if (sp->ap) {
+ sp->ap->flag &= ~ALIASINUSE;
+ if (sp->ap->flag & ALIASDEAD) unalias(sp->ap->name);
+ }
+ psp = sp;
+ sp = sp->spfree;
+ if (psp != &(parsefile->basestrpush)) ckfree(psp);
+ } while (sp);
+ parsefile->spfree = NULL;
+ INTON;
+}
+
+static int pgetc_nofree(void) {
int c;
if (parsefile->unget) return parsefile->lastc[--parsefile->unget];
if (--parsefile->nleft >= 0)
@@ -5612,14 +5646,13 @@
}
/*
- * Same as pgetc(), but ignores PEOA.
+ * Read a character from the script, returning PEOF on end of file.
+ * Nul characters in the input are silently discarded.
*/
-static int pgetc2() {
- int c;
- do {
- c = pgetc();
- } while (c == PEOA);
- return c;
+int pgetc(void) {
+ struct strpush *sp = parsefile->spfree;
+ if (unlikely(sp)) freestrings(sp);
+ return pgetc_nofree();
}
static void AddUniqueCompletion(linenoiseCompletions *c, char *s) {
@@ -5774,12 +5807,8 @@
int more;
char savec;
if (unlikely(parsefile->strpush)) {
- if (parsefile->nleft == -1 && parsefile->strpush->ap && parsefile->nextc[-1] != ' ' &&
- parsefile->nextc[-1] != '\t') {
- return PEOA;
- }
popstring();
- return pgetc();
+ return pgetc_nofree();
}
if (unlikely(parsefile->nleft == EOF_NLEFT || parsefile->buf == NULL)) return PEOF;
flushall();
@@ -5840,7 +5869,7 @@
len = strlen(s);
INTOFF;
/*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
- if (parsefile->strpush) {
+ if ((unsigned long)parsefile->strpush | (unsigned long)parsefile->spfree) {
sp = ckmalloc(sizeof(struct strpush));
sp->prev = parsefile->strpush;
parsefile->strpush = sp;
@@ -5849,6 +5878,7 @@
sp->prevstring = parsefile->nextc;
sp->prevnleft = parsefile->nleft;
sp->unget = parsefile->unget;
+ sp->spfree = parsefile->spfree;
memcpy(sp->lastc, parsefile->lastc, sizeof(sp->lastc));
sp->ap = (struct alias *)ap;
if (ap) {
@@ -5858,6 +5888,7 @@
parsefile->nextc = s;
parsefile->nleft = len;
parsefile->unget = 0;
+ parsefile->spfree = NULL;
INTON;
}
@@ -5871,10 +5902,6 @@
if (sp->string != sp->ap->val) {
ckfree(sp->string);
}
- sp->ap->flag &= ~ALIASINUSE;
- if (sp->ap->flag & ALIASDEAD) {
- unalias(sp->ap->name);
- }
}
parsefile->nextc = sp->prevstring;
parsefile->nleft = sp->prevnleft;
@@ -5882,7 +5909,7 @@
memcpy(parsefile->lastc, sp->lastc, sizeof(sp->lastc));
/*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
parsefile->strpush = sp->prev;
- if (sp != &(parsefile->basestrpush)) ckfree(sp);
+ parsefile->spfree = sp;
INTON;
}
@@ -5893,11 +5920,8 @@
static int setinputfile(const char *fname, int flags) {
int fd;
INTOFF;
- if ((fd = open(fname, O_RDONLY, 0)) < 0) {
- if (flags & INPUT_NOFILE_OK) goto out;
- exitstatus = 127;
- exerror(EXERROR, "Can't open %s", fname);
- }
+ fd = sh_open(fname, O_RDONLY, flags & INPUT_NOFILE_OK);
+ if (fd < 0) goto out;
if (fd < 10) fd = savefd(fd, fd);
setinputfd(fd, flags & INPUT_PUSH_FILE);
out:
@@ -5943,6 +5967,7 @@
pf->prev = parsefile;
pf->fd = -1;
pf->strpush = NULL;
+ pf->spfree = NULL;
pf->basestrpush.prev = NULL;
pf->unget = 0;
parsefile = pf;
@@ -5953,7 +5978,11 @@
INTOFF;
if (pf->fd >= 0) close(pf->fd);
if (pf->buf) ckfree(pf->buf);
- while (pf->strpush) popstring();
+ if (parsefile->spfree) freestrings(parsefile->spfree);
+ while (pf->strpush) {
+ popstring();
+ freestrings(parsefile->spfree);
+ }
parsefile = pf->prev;
ckfree(pf);
INTON;
@@ -5970,18 +5999,6 @@
unwindfiles(&basepf);
}
-/*
- * Close the file(s) that the shell is reading commands from. Called
- * after a fork is done.
- */
-static void closescript(void) {
- popallfiles();
- if (parsefile->fd > 0) {
- close(parsefile->fd);
- parsefile->fd = 0;
- }
-}
-
static char *commandtext(union node *);
static int dowait(int, struct job *);
static int getstatus(struct job *);
@@ -6052,7 +6069,7 @@
if (on == jobctl || rootshell == 0) return;
if (on) {
int ofd;
- ofd = fd = open(_PATH_TTY, O_RDWR, 0);
+ ofd = fd = sh_open(_PATH_TTY, O_RDWR, 1);
if (fd < 0) {
fd += 3;
while (!isatty(fd))
@@ -6322,8 +6339,8 @@
static void showjobs(struct output *out, int mode) {
struct job *jp;
TRACE(("showjobs(%x) called\n", mode));
- /* If not even one one job changed, there is nothing to do */
- dowait(DOWAIT_NORMAL, NULL);
+ /* If not even one job changed, there is nothing to do */
+ dowait(DOWAIT_NONBLOCK, NULL);
for (jp = curjob; jp; jp = jp->prev_job) {
if (!(mode & SHOW_CHANGED) || jp->changed) showjob(out, jp, mode);
}
@@ -6365,7 +6382,7 @@
jp->waited = 1;
jp = jp->prev_job;
}
- if (!dowait(DOWAIT_WAITCMD, 0)) goto sigout;
+ if (!dowait(DOWAIT_WAITCMD_ALL, 0)) goto sigout;
}
}
retval = 127;
@@ -6546,8 +6563,7 @@
lvforked = vforked;
if (!lvforked) {
shlvl++;
- closescript();
- clear_traps();
+ forkreset();
/* do job control only in root shell */
jobctl = 0;
}
@@ -6567,14 +6583,12 @@
ignoresig(SIGQUIT);
if (jp->nprocs == 0) {
close(0);
- if (open(_PATH_DEVNULL, O_RDONLY, 0) != 0) sh_error("Can't open %s", _PATH_DEVNULL);
+ sh_open(_PATH_DEVNULL, O_RDONLY, 0);
}
}
if (!oldlvl && iflag) {
- if (mode != FORK_BG) {
- setsignal(SIGINT);
- setsignal(SIGQUIT);
- }
+ setsignal(SIGINT);
+ setsignal(SIGQUIT);
setsignal(SIGTERM);
}
if (lvforked) return;
@@ -6666,7 +6680,7 @@
static int waitforjob(struct job *jp) {
int st;
TRACE(("waitforjob(%%%d) called\n", jp ? jobno(jp) : 0));
- dowait(jp ? DOWAIT_BLOCK : DOWAIT_NORMAL, jp);
+ dowait(jp ? DOWAIT_BLOCK : DOWAIT_NONBLOCK, jp);
if (!jp) return exitstatus;
st = getstatus(jp);
if (jp->jobctl) {
@@ -6750,12 +6764,19 @@
}
static int dowait(int block, struct job *jp) {
- int pid = block == DOWAIT_NORMAL ? gotsigchld : 1;
- while (jp ? jp->state == JOBRUNNING : pid > 0) {
- if (!jp) gotsigchld = 0;
+ int gotchld = *(volatile int *)&gotsigchld;
+ int rpid;
+ int pid;
+ if (jp && jp->state != JOBRUNNING) block = DOWAIT_NONBLOCK;
+ if (block == DOWAIT_NONBLOCK && !gotchld) return 1;
+ rpid = 1;
+ do {
pid = waitone(block, jp);
- }
- return pid;
+ rpid &= !!pid;
+ block &= ~DOWAIT_WAITCMD_ALL;
+ if (!pid || (jp && jp->state != JOBRUNNING)) block = DOWAIT_NONBLOCK;
+ } while (pid >= 0);
+ return rpid;
}
/*
@@ -6778,12 +6799,13 @@
int err;
if (jobctl) flags |= WUNTRACED;
do {
- err = wait3(status, flags, NULL);
+ gotsigchld = 0;
+ do err = wait3(status, flags, NULL);
+ while (err < 0 && errno == EINTR);
if (err || (err = -!block)) break;
sigblockall(&oldmask);
while (!gotsigchld && !pending_sig) sigsuspend(&oldmask);
sigclearmask();
- err = 0;
} while (gotsigchld);
return err;
}
@@ -7062,7 +7084,11 @@
}
static void xtcsetpgrp(int fd, int pgrp) {
- if (tcsetpgrp(fd, pgrp)) sh_error("Cannot set tty process group (%s)", strerror(errno));
+ int err;
+ sigblockall(NULL);
+ err = tcsetpgrp(fd, pgrp);
+ sigclearmask();
+ if (err) sh_error("Cannot set tty process group (%s)", strerror(errno));
}
static int getstatus(struct job *job) {
@@ -7458,7 +7484,6 @@
setinputfile(*xargv, 0);
setarg0:
arg0 = *xargv++;
- commandname = arg0;
}
shellparam.p = xargv;
shellparam.optind = 1;
@@ -7803,22 +7828,27 @@
}
static union node *list(int nlflag) {
+ int chknl = nlflag & 1 ? 0 : CHKNL;
union node *n1, *n2, *n3;
int tok;
n1 = NULL;
for (;;) {
- switch (peektoken()) {
+ checkkwd = chknl | CHKKWD | CHKALIAS;
+ tok = readtoken();
+ switch (tok) {
case TNL:
- if (!(nlflag & 1)) break;
parseheredoc();
return n1;
case TEOF:
- if (!n1 && (nlflag & 1)) n1 = NEOF;
+ if (!n1 && !chknl) n1 = NEOF;
+ out_eof:
parseheredoc();
+ tokpushback++;
+ lasttoken = TEOF;
return n1;
}
- checkkwd = CHKNL | CHKKWD | CHKALIAS;
- if (nlflag == 2 && tokendlist[peektoken()]) return n1;
+ tokpushback++;
+ if (nlflag == 2 && tokendlist[tok]) return n1;
nlflag |= 2;
n2 = andor();
tok = readtoken();
@@ -7845,15 +7875,16 @@
n1 = n3;
}
switch (tok) {
- case TNL:
case TEOF:
+ goto out_eof;
+ case TNL:
tokpushback++;
/* fall through */
case TBACKGND:
case TSEMI:
break;
default:
- if ((nlflag & 1)) synexpect(-1);
+ if (!chknl) synexpect(-1);
tokpushback++;
return n1;
}
@@ -8248,13 +8279,6 @@
}
}
-static int peektoken(void) {
- int t;
- t = readtoken();
- tokpushback++;
- return (t);
-}
-
static int readtoken(void) {
int t;
int kwd = checkkwd;
@@ -8266,9 +8290,12 @@
if (kwd & CHKNL) {
while (t == TNL) {
parseheredoc();
+ checkkwd = 0;
t = xxreadtoken();
}
}
+ kwd |= checkkwd;
+ checkkwd = 0;
if (t != TWORD || quoteflag) {
goto out;
}
@@ -8284,7 +8311,7 @@
goto out;
}
}
- if (checkkwd & CHKALIAS) {
+ if (kwd & CHKALIAS) {
struct alias *ap;
if ((ap = lookupalias(wordtext, 1)) != NULL) {
if (*ap->val) {
@@ -8294,7 +8321,6 @@
}
}
out:
- checkkwd = 0;
return (t);
}
@@ -8338,7 +8364,6 @@
switch (c) {
case ' ':
case '\t':
- case PEOA:
continue;
case '#':
while ((c = pgetc()) != '\n' && c != PEOF)
@@ -8376,7 +8401,7 @@
static int pgetc_eatbnl(void) {
int c;
while ((c = pgetc()) == '\\') {
- if (pgetc2() != '\n') {
+ if (pgetc() != '\n') {
pungetc();
break;
}
@@ -8481,7 +8506,7 @@
break;
/* backslash */
case CBACK:
- c = pgetc2();
+ c = pgetc();
if (c == PEOF) {
USTPUTC(CTLESC, out);
USTPUTC('\\', out);
@@ -8568,13 +8593,9 @@
break;
case CEOF:
goto endword; /* exit outer loop */
- case CIGN:
- break;
default:
if (synstack->varnest == 0) goto endword; /* exit outer loop */
- if (c != PEOA) {
- USTPUTC(c, out);
- }
+ USTPUTC(c, out);
}
c = pgetc_top(synstack);
}
@@ -8613,18 +8634,13 @@
if (realeofmark(eofmark)) {
int markloc;
char *p;
- if (c == PEOA) {
- c = pgetc2();
- }
if (striptabs) {
- while (c == '\t') {
- c = pgetc2();
- }
+ while (c == '\t') c = pgetc();
}
markloc = out - (char *)stackblock();
for (p = eofmark; STPUTC(c, out), *p; p++) {
if (c != *p) goto more_heredoc;
- c = pgetc2();
+ c = pgetc();
}
if (c == '\n' || c == PEOF) {
c = PEOF;
@@ -8717,8 +8733,7 @@
char *p;
static const char types[] = "}-+?=";
c = pgetc_eatbnl();
- if ((checkkwd & CHKEOFMARK) || c <= PEOA ||
- (c != '(' && c != '{' && !is_name(c) && !is_special(c))) {
+ if ((checkkwd & CHKEOFMARK) || (c != '(' && c != '{' && !is_name(c) && !is_special(c))) {
USTPUTC('$', out);
pungetc();
} else if (c == '(') { /* $(command) or $((arith)) */
@@ -8748,7 +8763,7 @@
do {
STPUTC(c, out);
c = pgetc_eatbnl();
- } while (is_digit(c));
+ } while ((subtype <= 0 || subtype >= VSLENGTH) && is_digit(c));
} else if (c != '}') {
int cc = c;
c = pgetc_eatbnl();
@@ -8795,6 +8810,7 @@
break;
}
} else {
+ if (subtype == VSLENGTH && c != '}') subtype = 0;
badsub:
pungetc();
}
@@ -8850,15 +8866,11 @@
case '`':
goto done;
case '\\':
- pc = pgetc_eatbnl();
+ pc = pgetc();
if (pc != '\\' && pc != '`' && pc != '$' && (!synstack->dblquote || pc != '"'))
STPUTC('\\', pout);
- if (pc > PEOA) {
- break;
- }
- /* fall through */
+ break;
case PEOF:
- case PEOA:
synerror("EOF in backquote substitution");
case '\n':
nlnoprompt();
@@ -8892,8 +8904,8 @@
else {
if (readtoken() != TRP) synexpect(TRP);
setinputstring(nullstr);
- parseheredoc();
}
+ parseheredoc();
heredoclist = saveheredoclist;
(*nlpp)->n = n;
/* Start reading from old file again. */
@@ -8938,21 +8950,38 @@
}
static const char *expandstr(const char *ps) {
- union node n;
+ struct parsefile *file_stop;
+ struct jmploc *volatile savehandler;
+ struct heredoc *saveheredoclist;
+ const char *result;
int saveprompt;
- /* XXX Fix (char *) cast. */
- setinputstring((char *)ps);
+ struct jmploc jmploc;
+ union node n;
+ int err;
+ file_stop = parsefile;
+ setinputstring((char *)ps); /* XXX Fix (char *) cast. */
+ saveheredoclist = heredoclist;
+ heredoclist = NULL;
saveprompt = doprompt;
doprompt = 0;
+ result = ps;
+ savehandler = handler;
+ if (unlikely(err = setjmp(jmploc.loc))) goto out;
+ handler = &jmploc;
readtoken1(pgetc_eatbnl(), DQSYNTAX, FAKEEOFMARK, 0);
- doprompt = saveprompt;
- popfile();
n.narg.type = NARG;
n.narg.next = NULL;
n.narg.text = wordtext;
n.narg.backquote = backquotelist;
expandarg(&n, NULL, EXP_QUOTED);
- return stackblock();
+ result = stackblock();
+out:
+ handler = savehandler;
+ if (err && exception != EXERROR) longjmp(handler->loc, 1);
+ doprompt = saveprompt;
+ unwindfiles(file_stop);
+ heredoclist = saveheredoclist;
+ return result;
}
/*
@@ -8979,6 +9008,16 @@
return findstring(s, parsekwd, sizeof(parsekwd) / sizeof(const char *));
}
+static unsigned update_closed_redirs(int fd, int nfd) {
+ unsigned val = closed_redirs;
+ unsigned bit = 1 << fd;
+ if (nfd >= 0)
+ closed_redirs &= ~bit;
+ else
+ closed_redirs |= bit;
+ return val & bit;
+}
+
/*
* Process a list of redirection commands. If the REDIR_PUSH flag is set,
* old file descriptors are stashed away so that the redirection can be
@@ -9003,17 +9042,17 @@
if (newfd < -1) continue;
fd = n->nfile.fd;
if (sv) {
+ int closed;
p = &sv->renamed[fd];
i = *p;
+ closed = update_closed_redirs(fd, newfd);
if (likely(i == EMPTY)) {
i = CLOSED;
- if (fd != newfd) {
+ if (fd != newfd && !closed) {
i = savefd(fd, fd);
fd = -1;
}
}
- if (i == newfd) /* Can only happen if i == newfd == CLOSED */
- i = REALLY_CLOSED;
*p = i;
}
if (fd == newfd) continue;
@@ -9023,47 +9062,66 @@
if (flags & REDIR_SAVEFD2 && sv->renamed[2] >= 0) preverrout.fd = sv->renamed[2];
}
+wontreturn static int sh_open_fail(const char *pathname, int flags, int e) {
+ const char *word;
+ int action;
+ word = "open";
+ action = E_OPEN;
+ if (flags & O_CREAT) {
+ word = "create";
+ action = E_CREAT;
+ }
+ sh_error("cannot %s %s: %s", word, pathname, errmsg(e, action));
+}
+
+static int sh_open(const char *pathname, int flags, int mayfail) {
+ int fd;
+ int e;
+ do {
+ fd = open(pathname, flags, 0666);
+ e = errno;
+ } while (fd < 0 && e == EINTR && !pending_sig);
+ if (mayfail || fd >= 0) return fd;
+ sh_open_fail(pathname, flags, e);
+}
+
static int openredirect(union node *redir) {
struct stat sb;
char *fname;
+ int flags;
int f;
switch (redir->nfile.type) {
case NFROM:
- fname = redir->nfile.expfname;
- if ((f = open(fname, O_RDONLY, 0)) < 0) goto eopen;
+ flags = O_RDONLY;
+ do_open:
+ f = sh_open(redir->nfile.expfname, flags, 0);
break;
case NFROMTO:
- fname = redir->nfile.expfname;
- if ((f = open(fname, O_RDWR | O_CREAT, 0666)) < 0) goto ecreate;
- break;
+ flags = O_RDWR|O_CREAT;
+ goto do_open;
case NTO:
/* Take care of noclobber mode. */
if (Cflag) {
fname = redir->nfile.expfname;
if (stat(fname, &sb) < 0) {
- if ((f = open(fname, O_WRONLY | O_CREAT | O_EXCL, 0666)) < 0) goto ecreate;
- } else if (!S_ISREG(sb.st_mode)) {
- if ((f = open(fname, O_WRONLY, 0666)) < 0) goto ecreate;
- if (!fstat(f, &sb) && S_ISREG(sb.st_mode)) {
- close(f);
- errno = EEXIST;
- goto ecreate;
- }
- } else {
- errno = EEXIST;
+ flags = O_WRONLY|O_CREAT|O_EXCL;
+ goto do_open;
+ }
+ if (S_ISREG(sb.st_mode)) goto ecreate;
+ f = sh_open(fname, O_WRONLY, 0);
+ if (!fstat(f, &sb) && S_ISREG(sb.st_mode)) {
+ close(f);
goto ecreate;
}
break;
}
/* FALLTHROUGH */
case NCLOBBER:
- fname = redir->nfile.expfname;
- if ((f = open(fname, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0) goto ecreate;
- break;
+ flags = O_WRONLY|O_CREAT|O_TRUNC;
+ goto do_open;
case NAPPEND:
- fname = redir->nfile.expfname;
- if ((f = open(fname, O_WRONLY | O_CREAT | O_APPEND, 0666)) < 0) goto ecreate;
- break;
+ flags = O_WRONLY|O_CREAT|O_APPEND;
+ goto do_open;
case NTOFD:
case NFROMFD:
f = redir->ndup.dupfd;
@@ -9078,9 +9136,7 @@
}
return f;
ecreate:
- sh_error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
-eopen:
- sh_error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
+ sh_open_fail(fname, O_CREAT, EEXIST);
}
static void dupredirect(union node *redir, int f) {
@@ -9148,13 +9204,13 @@
int i;
INTOFF;
rp = redirlist;
- for (i = 0; i < 10; i++) {
+ for (i = 0 ; i < 10 ; i++) {
+ int closed;
+ if (rp->renamed[i] == EMPTY) continue;
+ closed = drop ? 1 : update_closed_redirs(i, rp->renamed[i]);
switch (rp->renamed[i]) {
case CLOSED:
- if (!drop) close(i);
- break;
- case EMPTY:
- case REALLY_CLOSED:
+ if (!closed) close(i);
break;
default:
if (!drop) dup2(rp->renamed[i], i);
@@ -9268,23 +9324,6 @@
return 0;
}
-/*
- * Clear traps on a fork.
- */
-static void clear_traps(void) {
- char **tp;
- INTOFF;
- for (tp = trap; tp < &trap[NSIG]; tp++) {
- if (*tp && **tp) { /* trap not NULL or SIG_IGN */
- ckfree(*tp);
- *tp = NULL;
- if (tp != &trap[0]) setsignal(tp - trap);
- }
- }
- trapcnt = 0;
- INTON;
-}
-
/*
* Set the signal handler for the specified signal. The routine figures
* out what it should be set to.
@@ -9437,15 +9476,17 @@
trap[0] = NULL;
evalskip = 0;
evalstring(p, 0);
+ evalskip = SKIPFUNCDEF;
}
out:
+ exitreset();
/*
* Disable job control so that whoever had the foreground before we
* started can get it back.
*/
if (likely(!setjmp(loc.loc))) setjobctl(0);
flushall();
- _exit(savestatus);
+ _exit(exitstatus);
}
static int decode_signal(const char *string, int minsig) {
@@ -10104,12 +10145,23 @@
static int timescmd() {
struct tms buf;
long int clk_tck = sysconf(_SC_CLK_TCK);
+ int mutime, mstime, mcutime, mcstime;
+ double utime, stime, cutime, cstime;
times(&buf);
- Printf("%dm%fs %dm%fs\n%dm%fs %dm%fs\n", (int)(buf.tms_utime / clk_tck / 60),
- ((double)buf.tms_utime) / clk_tck, (int)(buf.tms_stime / clk_tck / 60),
- ((double)buf.tms_stime) / clk_tck, (int)(buf.tms_cutime / clk_tck / 60),
- ((double)buf.tms_cutime) / clk_tck, (int)(buf.tms_cstime / clk_tck / 60),
- ((double)buf.tms_cstime) / clk_tck);
+ utime = (double)buf.tms_utime / clk_tck;
+ mutime = utime / 60;
+ utime -= mutime * 60.0;
+ stime = (double)buf.tms_stime / clk_tck;
+ mstime = stime / 60;
+ stime -= mstime * 60.0;
+ cutime = (double)buf.tms_cutime / clk_tck;
+ mcutime = cutime / 60;
+ cutime -= mcutime * 60.0;
+ cstime = (double)buf.tms_cstime / clk_tck;
+ mcstime = cstime / 60;
+ cstime -= mcstime * 60.0;
+ Printf("%dm%fs %dm%fs\n%dm%fs %dm%fs\n", mutime, utime, mstime, stime,
+ mcutime, cutime, mcstime, cstime);
return 0;
}
@@ -10402,7 +10454,7 @@
* Called after a function returns.
* Interrupts must be off.
*/
-static void poplocalvars(int keep) {
+static void poplocalvars(void) {
struct localvar_list *ll;
struct localvar *lvp, *next;
struct Var *vp;
@@ -10415,18 +10467,7 @@
next = lvp->next;
vp = lvp->vp;
TRACE(("poplocalvar %s\n", vp ? vp->text : "-"));
- if (keep) {
- int bits = VSTRFIXED;
- if (lvp->flags != VUNSET) {
- if (vp->text == lvp->text)
- bits |= VTEXTFIXED;
- else if (!(lvp->flags & (VTEXTFIXED | VSTACK)))
- ckfree(lvp->text);
- }
- vp->flags &= ~bits;
- vp->flags |= (lvp->flags & bits);
- if ((vp->flags & (VEXPORT | VREADONLY | VSTRFIXED | VUNSET)) == VUNSET) unsetvar(vp->text);
- } else if (vp == NULL) { /* $- saved */
+ if (vp == NULL) { /* $- saved */
memcpy(optlist, lvp->text, sizeof(optlist));
ckfree(lvp->text);
optschanged();
@@ -10463,7 +10504,7 @@
}
static void unwindlocalvars(struct localvar_list *stop) {
- while (localvar_stack != stop) poplocalvars(0);
+ while (localvar_stack != stop) poplocalvars();
}
/*
@@ -10506,8 +10547,7 @@
sigmode[SIGCHLD - 1] = S_DFL;
setsignal(SIGCHLD);
}
- /* from output.c: */
- {} /* from var.c: */
+ /* from var.c: */
{
char **envp;
static char ppid[32] = "PPID=";
@@ -10543,12 +10583,14 @@
static void exitreset() {
/* from eval.c: */
{
- evalskip = 0;
- loopnest = 0;
if (savestatus >= 0) {
- exitstatus = savestatus;
+ if (exception == EXEXIT || evalskip == SKIPFUNCDEF)
+ exitstatus = savestatus;
savestatus = -1;
}
+ evalskip = 0;
+ loopnest = 0;
+ inps4 = 0;
}
/* from expand.c: */
{ ifsfree(); }
@@ -10561,6 +10603,43 @@
}
}
+/*
+ * This routine is called when we enter a subshell.
+ */
+static void forkreset() {
+ /* from input.c: */
+ {
+ popallfiles();
+ if (parsefile->fd > 0) {
+ close(parsefile->fd);
+ parsefile->fd = 0;
+ }
+ }
+ /* from main.c: */
+ {
+ handler = &main_handler;
+ }
+ /* from redir.c: */
+ {
+ redirlist = NULL;
+ }
+ /* from trap.c: */
+ {
+ char **tp;
+ INTOFF;
+ for (tp = trap ; tp < &trap[NSIG] ; tp++) {
+ if (*tp && **tp) { /* trap not NULL or SIG_IGN */
+ ckfree(*tp);
+ *tp = NULL;
+ if (tp != &trap[0])
+ setsignal(tp - trap);
+ }
+ }
+ trapcnt = 0;
+ INTON;
+ }
+}
+
/*
* This routine is called when an error or an interrupt occurs in an
* interactive shell and control is returned to the main command loop.
@@ -10570,10 +10649,10 @@
{
/* clear input buffer */
basepf.lleft = basepf.nleft = 0;
+ basepf.unget = 0;
popallfiles();
}
- /* from output.c: */
- {} /* from var.c: */
+ /* from var.c: */
{
unwindlocalvars(0);
}
@@ -10815,11 +10894,17 @@
if (n == NEOF) {
if (!top || numeof >= 50) break;
if (!stoppedjobs()) {
- if (!Iflag) break;
+ if (!Iflag) {
+ if (iflag) {
+ outcslow('\n', out2);
+ flushout(out2);
+ }
+ break;
+ }
outstr("\nUse \"exit\" to leave shell.\n", out2);
}
numeof++;
- } else if (nflag == 0) {
+ } else {
int i;
job_warning = (job_warning == 2) ? 1 : 0;
numeof = 0;
@@ -10899,17 +10984,16 @@
int main(int argc, char **argv) {
char *shinit;
volatile int state;
- struct jmploc jmploc;
struct stackmark smark;
int login;
state = 0;
- if (unlikely(setjmp(jmploc.loc))) {
+ if (unlikely(setjmp(main_handler.loc))) {
int e;
int s;
exitreset();
e = exception;
s = state;
- if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) exitshell();
+ if (e == EXEND || e == EXEXIT || s == 0 || iflag == 0 || shlvl) exitshell();
reset();
if (e == EXINT) {
outcslow('\n', out2);
@@ -10926,7 +11010,7 @@
goto state4;
}
}
- handler = &jmploc;
+ handler = &main_handler;
rootpid = getpid();
init();
setstackmark(&smark);