doc/{bash.1,bashref.texi}
- slight change to the text describing the effect of set -e when
in a || or && list
+
+ 12/5
+ ----
+jobs.c
+ - fix raw_job_exit_status to correct mixing of int/WAIT values (need
+ to return a WAIT)
+ - arrange so that children run as part of command substitutions also
+ set the SIGINT handler to wait_sigint_handler, since they effectively
+ don't do job control
+ - in wait_for, if a child run as part of a command substitution exits
+ due to SIGINT, resend the SIGINT to the waiting shell with kill(2).
+ This makes sure the exit status propagates
+
+doc/{bash.1,bashref.texi}
+ - tighten up the language describing when bash tries to see if its
+ stdin is a socket, so it can run the startup files. Suggested by
+ Vincent Lefevre <vincent@vinc17.org>
+
+eval.c
+ - in the DISCARD case of a longjmp to top_level, make sure
+ last_command_exit_value is set to EXECUTION_FAILURE if it's 0,
+ but leave existing non-zero values alone
+
+subst.c
+ - in command_substitute, don't reset pipeline_pgrp in the child
+ process -- this means that second and subsequent children spawned by
+ this comsub shell get put into the wrong process group, not the
+ shell's. Fix for bug reported by Ingo Molnar <mingo@elte.hu>
+
+ 12/6
+ ----
+support/shobj-conf
+ - make sure the cases for darwin8.x (Mac OS X 10.4.x) are extended to
+ darwin9.x (Mac OS X 10.5.x). Fixes problem originally reported
+ against readline-5.2 by schneecrash@gmail.com
+
+ 12/8
+ ----
+subst.c
+ - make sure to add the results of (successful) tilde expansion as a
+ quoted string, to inhibit pathname expansion and word splitting.
+ From recent Austin Group interpretation.
+
+include/shtty.h, lib/sh/shtty.c
+ - add ttfd_onechar, ttfd_noecho, ttfd_eightbit, ttfd_nocanon, and
+ ttfd_cbreak to set tty attributes associated with a particular
+ file descriptor (which is presumed to point to a terminal)
+
+lib/readline/display.c
+ - make sure we only use rl_invis_chars_first_line when the number of
+ physical characters exceeds the screen width, since that's the
+ only time expand_prompt sets it to a valid value
----
builtins/read.def
- make sure the return value from get_word_from_string is freed if
- non-null. Fixes bug reported by Lars Ellenberg
+ non-null. Fixes memory leak bug reported by Lars Ellenberg
<lars.ellenberg@linbit.com>
11/10
doc/{bash.1,bashref.texi}
- slight change to the text describing the effect of set -e when
in a || or && list
+
+ 12/5
+ ----
+jobs.c
+ - fix raw_job_exit_status to correct mixing of int/WAIT values (need
+ to return a WAIT)
+ - arrange so that children run as part of command substitutions also
+ set the SIGINT handler to wait_sigint_handler, since they effectively
+ don't do job control
+ - in wait_for, if a child run as part of a command substitution exits
+ due to SIGINT, resend the SIGINT to the waiting shell with kill(2).
+ This makes sure the exit status propagates
+
+doc/{bash.1,bashref.texi}
+ - tighten up the language describing when bash tries to see if its
+ stdin is a socket, so it can run the startup files. Suggested by
+ Vincent Lefevre <vincent@vinc17.org>
+
+eval.c
+ - in the DISCARD case of a longjmp to top_level, make sure
+ last_command_exit_value is set to EXECUTION_FAILURE if it's 0,
+ but leave existing non-zero values alone
+
+subst.c
+ - in command_substitute, don't reset pipeline_pgrp in the child
+ process -- this means that second and subsequent children spawned by
+ this comsub shell get put into the wrong process group, not the
+ shell's. Fix for bug reported by Ingo Molnar <mingo@elte.hu>
+
+ 12/6
+ ----
+support/shobj-conf
+ - make sure the cases for darwin8.x (Mac OS X 10.4.x) are extended to
+ darwin9.x (Mac OS X 10.5.x). Fixes problem originally reported
+ against readline-5.2 by schneecrash@gmail.com
+
+ 12/8
+ ----
+subst.c
+ - make sure to add the results of (successful) tilde expansion as a
+ quoted string, to inhibit pathname expansion and word splitting.
+ From recent Austin Group interpretation.
+
+include/shtty.h, lib/sh/shtty.c
+ - add ttfd_onechar, ttfd_noecho, ttfd_eightbit, ttfd_nocanon, and
+ ttfd_cbreak to set tty attributes associated with a particular
+ file descriptor (which is presumed to point to the terminal)
+
+lib/readline/display.c
+ - make sure we only use rl_invis_chars_first_line when the number of
+ physical characters exceeds the screen width, since that's the
+ only time expand_prompt sets it to a valid value
/* #define NON_INTERACTIVE_LOGIN_SHELLS */
/* Define this if you want bash to try to check whether it's being run by
- sshd and source the .bashrc if so (like the rshd behavior). */
+ sshd and source the .bashrc if so (like the rshd behavior). This checks
+ for the presence of SSH_CLIENT or SSH2_CLIENT in the initial environment,
+ which can be fooled under certain not-uncommon circumstances. */
/* #define SSH_SOURCE_BASHRC */
/* This contains various user-settable options not under the control of
autoconf. */
-/* Copyright (C) 2002 Free Software Foundation, Inc.
+/* Copyright (C) 2002-2007 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
.\" Case Western Reserve University
.\" chet@po.cwru.edu
.\"
-.\" Last Change: Wed Nov 21 22:39:33 EST 2007
-
+.\" Last Change: Wed Dec 5 22:08:48 EST 2007
.\"
.\" bash_builtins, strip all but Built-Ins section
.if \n(zZ=1 .ig zZ
.if \n(zY=1 .ig zY
-.TH BASH 1 "2007 November 21" "GNU Bash-3.2"
+.TH BASH 1 "2007 December 5" "GNU Bash-3.2"
.\"
.\" There's some problem with having a `@'
.\" in a tagged paragraph with the BSD man macros.
No other startup files are read.
.PP
.B Bash
-attempts to determine when it is being run by the remote shell
-daemon, usually \fIrshd\fP.
+attempts to determine when it is being run with its standard input
+connected to a a network connection, as if by the remote shell
+daemon, usually \fIrshd\fP, or the secure shell daemon \fIsshd\fP.
If
.B bash
-determines it is being run by \fIrshd\fP, it reads and executes
+determines it is being run in this fashion, it reads and executes
commands from \fI~/.bashrc\fP, if that file exists and is readable.
It will not do this if invoked as \fBsh\fP.
The
@subsubheading Invoked by remote shell daemon
-Bash attempts to determine when it is being run by the remote shell
-daemon, usually @code{rshd}. If Bash determines it is being run by
-rshd, it reads and executes commands from @file{~/.bashrc}, if that
+Bash attempts to determine when it is being run with its standard input
+connected to a a network connection, as if by the remote shell
+daemon, usually @code{rshd}, or the secure shell daemon @code{sshd}.
+If Bash determines it is being run in
+this fashion, it reads and executes commands from @file{~/.bashrc}, if that
file exists and is readable.
It will not do this if invoked as @code{sh}.
The @option{--norc} option may be used to inhibit this behavior, and the
Copyright (C) 1988-2007 Free Software Foundation, Inc.
@end ignore
-@set LASTCHANGE Wed Nov 21 22:41:34 EST 2007
+@set LASTCHANGE Wed Dec 5 22:08:02 EST 2007
@set EDITION 3.2
@set VERSION 3.2
-@set UPDATED 21 November 2007
-@set UPDATED-MONTH November 2007
+@set UPDATED 5 December 2007
+@set UPDATED-MONTH December 2007
goto exec_done;
case DISCARD:
- last_command_exit_value = 1;
+ /* Make sure the exit status is reset to a non-zero value, but
+ leave existing non-zero values (e.g., > 128 on signal)
+ alone. */
+ if (last_command_exit_value == 0)
+ last_command_exit_value = EXECUTION_FAILURE;
if (subshell_environment)
{
current_command = (COMMAND *)NULL;
subshells forked to execute builtin commands (e.g., in
pipelines) to be waited for twice. */
exec_result = wait_for (last_made_pid);
-itrace("execute_command_internal: wait_for (%d) = %d", last_made_pid, exec_result);
}
}
#endif
last_command_exit_value = exec_result;
-itrace("execute_command_internal: last_command_exit_value -> %d last_command_exit_signal = %d", last_command_exit_value, last_command_exit_signal);
run_pending_traps ();
#if 0
if (running_trap == 0)
course), the right thing will happen, but more system calls will be
executed than absolutely necessary. You can do all of this yourself
with the other functions; these are only conveniences. */
+
+/* These functions work with a given file descriptor and set terminal
+ attributes */
+extern int ttfd_onechar __P((int, TTYSTRUCT *));
+extern int ttfd_noecho __P((int, TTYSTRUCT *));
+extern int ttfd_eightbit __P((int, TTYSTRUCT *));
+extern int ttfd_nocanon __P((int, TTYSTRUCT *));
+
+extern int ttfd_cbreak __P((int, TTYSTRUCT *));
+
+/* These functions work with fd 0 and the TTYSTRUCT saved with ttsave () */
extern int ttonechar __P((void));
extern int ttnoecho __P((void));
extern int tteightbit __P((void));
--- /dev/null
+/* Copyright (C) 1999 Free Software Foundation, Inc. */
+
+/* This file is part of GNU Bash, the Bourne Again SHell.
+
+ Bash is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 2, or (at your option) any later
+ version.
+
+ Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with Bash; see the file COPYING. If not, write to the Free Software
+ Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+/*
+ * shtty.h -- include the correct system-dependent files to manipulate the
+ * tty
+ */
+
+#ifndef __SH_TTY_H_
+#define __SH_TTY_H_
+
+#include "stdc.h"
+
+#if defined (_POSIX_VERSION) && defined (HAVE_TERMIOS_H) && defined (HAVE_TCGETATTR) && !defined (TERMIOS_MISSING)
+# define TERMIOS_TTY_DRIVER
+#else
+# if defined (HAVE_TERMIO_H)
+# define TERMIO_TTY_DRIVER
+# else
+# define NEW_TTY_DRIVER
+# endif
+#endif
+
+/*
+ * The _POSIX_SOURCE define is to avoid multiple symbol definitions
+ * between sys/ioctl.h and termios.h. Ditto for the test against SunOS4
+ * and the undefining of several symbols.
+ */
+
+#ifdef TERMIOS_TTY_DRIVER
+# if (defined (SunOS4) || defined (SunOS5)) && !defined (_POSIX_SOURCE)
+# define _POSIX_SOURCE
+# endif
+# if defined (SunOS4)
+# undef ECHO
+# undef NOFLSH
+# undef TOSTOP
+# endif /* SunOS4 */
+# include <termios.h>
+# define TTYSTRUCT struct termios
+#else
+# ifdef TERMIO_TTY_DRIVER
+# include <termio.h>
+# define TTYSTRUCT struct termio
+# else /* NEW_TTY_DRIVER */
+# include <sgtty.h>
+# define TTYSTRUCT struct sgttyb
+# endif
+#endif
+
+/* Functions imported from lib/sh/shtty.c */
+
+/* Get and set terminal attributes for the file descriptor passed as
+ an argument. */
+extern int ttgetattr __P((int, TTYSTRUCT *));
+extern int ttsetattr __P((int, TTYSTRUCT *));
+
+/* Save and restore the terminal's attributes from static storage. */
+extern void ttsave __P((void));
+extern void ttrestore __P((void));
+
+/* Return the attributes corresponding to the file descriptor (0 or 1)
+ passed as an argument. */
+extern TTYSTRUCT *ttattr __P((int));
+
+/* These functions only operate on the passed TTYSTRUCT; they don't
+ actually change anything with the kernel's current tty settings. */
+extern int tt_setonechar __P((TTYSTRUCT *));
+extern int tt_setnoecho __P((TTYSTRUCT *));
+extern int tt_seteightbit __P((TTYSTRUCT *));
+extern int tt_setnocanon __P((TTYSTRUCT *));
+extern int tt_setcbreak __P((TTYSTRUCT *));
+
+/* These functions are all generally mutually exclusive. If you call
+ more than one (bracketed with calls to ttsave and ttrestore, of
+ course), the right thing will happen, but more system calls will be
+ executed than absolutely necessary. You can do all of this yourself
+ with the other functions; these are only conveniences. */
+
+/* These functions work with a given file descriptor and set terminal
+ attributes */
+extern int ttfd_onechar __P((int, TTYSTRUCT *));
+extern int ttfd_noecho __P((int, TTYSTRUCT *));
+extern int ttfd_eightbit __P((int, TTYSTRUCT *));
+extern int ttfd_nocanon __P((int, TTYSTRUCT *));
+
+extern int ttcbreak __P((int, TTYSTRUCT *));
+
+/* These functions work with fd 0 and the TTYSTRUCT saved with ttsave () */
+extern int ttonechar __P((void));
+extern int ttnoecho __P((void));
+extern int tteightbit __P((void));
+extern int ttnocanon __P((void));
+
+extern int ttcbreak __P((void));
+
+#endif
static int job_exit_signal __P((int));
static int set_job_status_and_cleanup __P((int));
+static WAIT job_signal_status __P((int));
static WAIT raw_job_exit_status __P((int));
static void notify_of_job_status __P((void));
{
cleanup_the_pipeline ();
pipeline_pgrp = 0;
-itrace("start_pipeline: set pipeline_pgrp = 0");
#if defined (PGRP_PIPE)
pipe_close (pgrp_pipe);
#endif
the_pipeline = (PROCESS *)NULL;
newjob->pgrp = pipeline_pgrp;
pipeline_pgrp = 0;
-itrace("stop_pipeline: set pipeline_pgrp = 0");
newjob->flags = 0;
sigemptyset (&oset);
sigprocmask (SIG_BLOCK, &set, &oset);
-itrace("make_child start: pipeline_pgrp = %d", pipeline_pgrp);
-
making_children ();
#if defined (BUFFERED_INPUT)
process group. */
if (pipeline_pgrp == 0) /* This is the first child. */
-{
pipeline_pgrp = mypid;
-itrace("make_child: child proc: set pipeline_pgrp = %d (mypid)", pipeline_pgrp);
-}
/* Check for running command in backquotes. */
if (pipeline_pgrp == shell_pgrp)
shell's process group (we could be in the middle of a
pipeline, for example). */
if (async_p == 0 && pipeline_pgrp != shell_pgrp && ((subshell_environment&SUBSHELL_ASYNC) == 0))
-{
-itrace("make_child: give terminal to %d shell_pgrp = %d subshell_environment = %d", pipeline_pgrp, shell_pgrp, subshell_environment);
give_terminal_to (pipeline_pgrp, 0);
-}
#if defined (PGRP_PIPE)
if (pipeline_pgrp == mypid)
else /* Without job control... */
{
if (pipeline_pgrp == 0)
-{
pipeline_pgrp = shell_pgrp;
-itrace("make_child: child proc: set pipeline_pgrp = %d (shell_pgrp)", pipeline_pgrp);
-}
/* If these signals are set to SIG_DFL, we encounter the curious
situation of an interactive ^Z to a running process *working*
if (pipeline_pgrp == 0)
{
pipeline_pgrp = pid;
-itrace("make_child: parent proc: set pipeline_pgrp = %d (pid)", pipeline_pgrp);
/* Don't twiddle terminal pgrps in the parent! This is the bug,
not the good thing of twiddling them in the child! */
/* give_terminal_to (pipeline_pgrp, 0); */
else
{
if (pipeline_pgrp == 0)
-{
pipeline_pgrp = shell_pgrp;
-itrace("make_child: parent proc: set pipeline_pgrp = %d (shell_pgrp)", pipeline_pgrp);
-}
-
}
/* Place all processes into the jobs array regardless of the
/* XXX - should this be interrupt_state? If it is, the shell will act
as if it got the SIGINT interrupt. */
wait_sigint_received = 1;
-itrace("wait_sigint_handler: wait_sigint_received -> 1");
/* Otherwise effectively ignore the SIGINT and allow the running job to
be killed. */
SIGRETURN (0);
return (EXECUTION_SUCCESS);
}
+static WAIT
+job_signal_status (job)
+ int job;
+{
+ register PROCESS *p;
+ WAIT s;
+
+ p = jobs[job]->pipe;
+ do
+ {
+ s = p->status;
+ if (WIFSIGNALED(s) || WIFSTOPPED(s))
+ break;
+ p = p->next;
+ }
+ while (p != jobs[job]->pipe);
+
+ return s;
+}
+
/* Return the exit status of the last process in the pipeline for job JOB.
This is the exit status of the entire job. */
static WAIT
{
register PROCESS *p;
int fail;
+ WAIT ret;
if (pipefail_opt)
{
p = jobs[job]->pipe;
do
{
- if (WSTATUS (p->status) != EXECUTION_SUCCESS) fail = WSTATUS(p->status);
+ if (WSTATUS (p->status) != EXECUTION_SUCCESS)
+ fail = WSTATUS(p->status);
p = p->next;
}
while (p != jobs[job]->pipe);
- return fail;
+ WSTATUS (ret) = fail;
+ return ret;
}
for (p = jobs[job]->pipe; p->next != jobs[job]->pipe; p = p->next)
/* XXX */
if ((job != NO_JOB && JOBSTATE (job) == JSTOPPED) || WIFSTOPPED (child->status))
termination_state = 128 + WSTOPSIG (child->status);
-itrace("wait_for (%d): termination_state = %d last_command_exit_signal = %d", pid, termination_state, last_command_exit_signal);
if (job == NO_JOB || IS_JOBCONTROL (job))
{
to a signal. We might want to change this later to just check
the last process in the pipeline. If no process exits due to a
signal, S is left as the status of the last job in the pipeline. */
- p = jobs[job]->pipe;
- do
- {
- s = p->status;
- if (WIFSIGNALED(s) || WIFSTOPPED(s))
- break;
- p = p->next;
- }
- while (p != jobs[job]->pipe);
+ s = job_signal_status (job);
if (WIFSIGNALED (s) || WIFSTOPPED (s))
{
}
}
}
+ else if ((subshell_environment & SUBSHELL_COMSUB) && wait_sigint_received)
+ {
+ /* If waiting for a job in a subshell started to do command
+ substitution, simulate getting and being killed by the SIGINT to
+ pass the status back to our parent. */
+ s = job_signal_status (job);
+
+ if (WIFSIGNALED (s) && WTERMSIG (s) == SIGINT && signal_is_trapped (SIGINT) == 0)
+ {
+ UNBLOCK_CHILD (oset);
+ restore_sigint_handler ();
+ old_sigint_handler = set_signal_handler (SIGINT, SIG_DFL);
+ if (old_sigint_handler == SIG_IGN)
+ restore_sigint_handler ();
+ else
+ kill (getpid (), SIGINT);
+ }
+ }
/* Moved here from set_job_status_and_cleanup, which is in the SIGCHLD
signal handler path */
wcontinued = 0;
continue; /* jump back to the test and retry without WCONTINUED */
}
-itrace("waitchld: waitpid returns %d (status %d)", pid, status);
/* The check for WNOHANG is to make sure we decrement sigchld only
if it was non-zero before we called waitpid. */
/* If we're turning on job control, reset pipeline_pgrp so make_child will
put new child processes into the right pgrp */
if (job_control != old && job_control)
-{
pipeline_pgrp = 0;
-itrace("set_job_control: set pipeline_pgrp = 0");
-}
return (old);
}
/* The number of additional slots to allocate when we run out. */
#define JOB_SLOTS 8
-#define CTTYFD 2
-
typedef int sh_job_map_func_t __P((JOB *, int, int, int));
/* Variables used here but defined in other files. */
static int job_exit_signal __P((int));
static int set_job_status_and_cleanup __P((int));
+static WAIT job_signal_status __P((int));
static WAIT raw_job_exit_status __P((int));
static void notify_of_job_status __P((void));
char *command;
int async_p;
{
+ int forksleep;
sigset_t set, oset;
pid_t pid;
sync_buffered_stream (default_buffered_input);
#endif /* BUFFERED_INPUT */
- /* Create the child, handle severe errors. */
- if ((pid = fork ()) < 0)
+ /* Create the child, handle severe errors. Retry on EAGAIN. */
+ while ((pid = fork ()) < 0 && errno == EAGAIN && forksleep < FORKSLEEP_MAX)
+ {
+ sys_error ("fork: retry");
+ if (sleep (forksleep) != 0)
+ break;
+ forksleep <<= 1;
+ }
+
+ if (pid < 0)
{
sys_error ("fork");
/* XXX - should this be interrupt_state? If it is, the shell will act
as if it got the SIGINT interrupt. */
wait_sigint_received = 1;
-
/* Otherwise effectively ignore the SIGINT and allow the running job to
be killed. */
SIGRETURN (0);
return (EXECUTION_SUCCESS);
}
+static WAIT
+job_signal_status (job)
+ int job;
+{
+ register PROCESS *p;
+ WAIT s;
+
+ p = jobs[job]->pipe;
+ do
+ {
+ s = p->status;
+ if (WIFSIGNALED(s) || WIFSTOPPED(s))
+ break;
+ p = p->next;
+ }
+ while (p != jobs[job]->pipe);
+
+ return s;
+}
+
/* Return the exit status of the last process in the pipeline for job JOB.
This is the exit status of the entire job. */
static WAIT
{
register PROCESS *p;
int fail;
+ WAIT ret;
if (pipefail_opt)
{
p = jobs[job]->pipe;
do
{
- if (WSTATUS (p->status) != EXECUTION_SUCCESS) fail = WSTATUS(p->status);
+ if (WSTATUS (p->status) != EXECUTION_SUCCESS)
+ fail = WSTATUS(p->status);
p = p->next;
}
while (p != jobs[job]->pipe);
- return fail;
+ WSTATUS (ret) = fail;
+ return ret;
}
for (p = jobs[job]->pipe; p->next != jobs[job]->pipe; p = p->next)
to finish. We don't want the shell to exit if an interrupt is
received, only if one of the jobs run is killed via SIGINT. If
job control is not set, the job will be run in the same pgrp as
- the shell, and the shell will see any signals the job gets. */
+ the shell, and the shell will see any signals the job gets. In
+ fact, we want this set every time the waiting shell and the waited-
+ for process are in the same process group, including command
+ substitution. */
/* This is possibly a race condition -- should it go in stop_pipeline? */
wait_sigint_received = 0;
- if (job_control == 0)
+ if (job_control == 0 || (subshell_environment&SUBSHELL_COMSUB))
{
old_sigint_handler = set_signal_handler (SIGINT, wait_sigint_handler);
if (old_sigint_handler == SIG_IGN)
to a signal. We might want to change this later to just check
the last process in the pipeline. If no process exits due to a
signal, S is left as the status of the last job in the pipeline. */
- p = jobs[job]->pipe;
- do
- {
- s = p->status;
- if (WIFSIGNALED(s) || WIFSTOPPED(s))
- break;
- p = p->next;
- }
- while (p != jobs[job]->pipe);
+ s = job_signal_status (job);
if (WIFSIGNALED (s) || WIFSTOPPED (s))
{
}
}
}
+ else if ((subshell_environment & SUBSHELL_COMSUB) && wait_sigint_received)
+ {
+ /* If waiting for a job in a subshell started to do command
+ substitution, simulate getting and being killed by the SIGINT to
+ pass the status back to our parent. */
+ s = job_signal_status (job);
+
+ if (WIFSIGNALED (s) && WTERMSIG (s) == SIGINT && signal_is_trapped (SIGINT) == 0)
+ {
+ UNBLOCK_CHILD (oset);
+ restore_sigint_handler ();
+ old_sigint_handler = set_signal_handler (SIGINT, SIG_DFL);
+ if (old_sigint_handler == SIG_IGN)
+ restore_sigint_handler ();
+ else
+ kill (getpid (), SIGINT);
+ }
+ }
/* Moved here from set_job_status_and_cleanup, which is in the SIGCHLD
signal handler path */
else
{
shell_tty = -1;
+
+ /* If forced_interactive is set, we skip the normal check that stderr
+ is attached to a tty, so we need to check here. If it's not, we
+ need to see whether we have a controlling tty by opening /dev/tty,
+ since trying to use job control tty pgrp manipulations on a non-tty
+ is going to fail. */
if (forced_interactive && isatty (fileno (stderr)) == 0)
shell_tty = open ("/dev/tty", O_RDWR|O_NONBLOCK);
{
#if defined (DEBUG)
if (i < js.j_firstj && jobs[i])
- itrace("count_all_jobs: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
+ itrace<("count_all_jobs: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
if (i > js.j_lastj && jobs[i])
itrace("count_all_jobs: job %d non-null after js.j_lastj (%d)", i, js.j_lastj);
#endif
second and subsequent lines start at inv_lbreaks[N], offset by
OFFSET (which has already been calculated above). */
+#define INVIS_FIRST() (prompt_physical_chars > _rl_screenwidth ? prompt_invis_chars_first_line : wrap_offset)
#define WRAP_OFFSET(line, offset) ((line == 0) \
- ? (offset ? prompt_invis_chars_first_line : 0) \
+ ? (offset ? INVIS_FIRST() : 0) \
: ((line == prompt_last_screen_line) ? wrap_offset-prompt_invis_chars_first_line : 0))
#define W_OFFSET(line, offset) ((line) == 0 ? offset : 0)
#define VIS_LLEN(l) ((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l]))
ttsaved = 0;
}
-/* Retrieve the attributes associated with tty fd FD. */
+/* Retrieve the internally-saved attributes associated with tty fd FD. */
TTYSTRUCT *
ttattr (fd)
int fd;
return 0;
}
+/* Set the tty associated with FD and TTP into one-character-at-a-time mode */
+int
+ttfd_onechar (fd, ttp)
+ int fd;
+ TTYSTRUCT *ttp;
+{
+ if (tt_setonechar(ttp) < 0)
+ return -1;
+ return (ttsetattr (fd, ttp));
+}
+
/* Set the terminal into one-character-at-a-time mode */
int
ttonechar ()
if (ttsaved == 0)
return -1;
tt = ttin;
- if (tt_setonechar(&tt) < 0)
- return -1;
- return (ttsetattr (0, &tt));
+ return (ttfd_onechar (0, &tt));
}
/*
return 0;
}
+/* Set the tty associated with FD and TTP into no-echo mode */
+int
+ttfd_noecho (fd, ttp)
+ int fd;
+ TTYSTRUCT *ttp;
+{
+ if (tt_setnoecho (ttp) < 0)
+ return -1;
+ return (ttsetattr (fd, ttp));
+}
+
/* Set the terminal into no-echo mode */
int
ttnoecho ()
if (ttsaved == 0)
return -1;
tt = ttin;
- if (tt_setnoecho (&tt) < 0)
- return -1;
- return (ttsetattr (0, &tt));
+ return (ttfd_noecho (0, &tt));
}
/*
return 0;
}
+/* Set the tty associated with FD and TTP into eight-bit mode */
+int
+ttfd_eightbit (fd, ttp)
+ int fd;
+ TTYSTRUCT *ttp;
+{
+ if (tt_seteightbit (ttp) < 0)
+ return -1;
+ return (ttsetattr (fd, ttp));
+}
+
/* Set the terminal into eight-bit mode */
int
tteightbit ()
if (ttsaved == 0)
return -1;
tt = ttin;
- if (tt_seteightbit (&tt) < 0)
- return -1;
- return (ttsetattr (0, &tt));
+ return (ttfd_eightbit (0, &tt));
}
/*
return 0;
}
+/* Set the tty associated with FD and TTP into non-canonical mode */
+int
+ttfd_nocanon (fd, ttp)
+ int fd;
+ TTYSTRUCT *ttp;
+{
+ if (tt_setnocanon (ttp) < 0)
+ return -1;
+ return (ttsetattr (fd, ttp));
+}
+
/* Set the terminal into non-canonical mode */
int
ttnocanon ()
if (ttsaved == 0)
return -1;
tt = ttin;
- if (tt_setnocanon (&tt) < 0)
- return -1;
- return (ttsetattr (0, &tt));
+ return (ttfd_nocanon (0, &tt));
}
/*
return (tt_setnoecho (ttp));
}
+/* Set the tty associated with FD and TTP into cbreak (no-echo,
+ one-character-at-a-time) mode */
+int
+ttfd_cbreak (fd, ttp)
+ int fd;
+ TTYSTRUCT *ttp;
+{
+ if (tt_setcbreak (ttp) < 0)
+ return -1;
+ return (ttsetattr (fd, ttp));
+}
+
/* Set the terminal into cbreak (no-echo, one-character-at-a-time) mode */
int
ttcbreak ()
if (ttsaved == 0)
return -1;
tt = ttin;
- if (tt_setcbreak (&tt) < 0)
- return -1;
- return (ttsetattr (0, &tt));
+ return (ttfd_cbreak (0, &tt));
}
--- /dev/null
+/* Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This file is part of GNU Bash, the Bourne Again SHell.
+
+ Bash is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 2, or (at your option) any later
+ version.
+
+ Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with Bash; see the file COPYING. If not, write to the Free Software
+ Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+/*
+ * shtty.c -- abstract interface to the terminal, focusing on capabilities.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#include <shtty.h>
+
+static TTYSTRUCT ttin, ttout;
+static int ttsaved = 0;
+
+int
+ttgetattr(fd, ttp)
+int fd;
+TTYSTRUCT *ttp;
+{
+#ifdef TERMIOS_TTY_DRIVER
+ return tcgetattr(fd, ttp);
+#else
+# ifdef TERMIO_TTY_DRIVER
+ return ioctl(fd, TCGETA, ttp);
+# else
+ return ioctl(fd, TIOCGETP, ttp);
+# endif
+#endif
+}
+
+int
+ttsetattr(fd, ttp)
+int fd;
+TTYSTRUCT *ttp;
+{
+#ifdef TERMIOS_TTY_DRIVER
+ return tcsetattr(fd, TCSADRAIN, ttp);
+#else
+# ifdef TERMIO_TTY_DRIVER
+ return ioctl(fd, TCSETAW, ttp);
+# else
+ return ioctl(fd, TIOCSETN, ttp);
+# endif
+#endif
+}
+
+void
+ttsave()
+{
+ if (ttsaved)
+ return;
+ ttgetattr (0, &ttin);
+ ttgetattr (1, &ttout);
+ ttsaved = 1;
+}
+
+void
+ttrestore()
+{
+ if (ttsaved == 0)
+ return;
+ ttsetattr (0, &ttin);
+ ttsetattr (1, &ttout);
+ ttsaved = 0;
+}
+
+/* Retrieve the internally-saved attributes associated with tty fd FD. */
+TTYSTRUCT *
+ttattr (fd)
+ int fd;
+{
+ if (ttsaved == 0)
+ return ((TTYSTRUCT *)0);
+ if (fd == 0)
+ return &ttin;
+ else if (fd == 1)
+ return &ttout;
+ else
+ return ((TTYSTRUCT *)0);
+}
+
+/*
+ * Change attributes in ttp so that when it is installed using
+ * ttsetattr, the terminal will be in one-char-at-a-time mode.
+ */
+int
+tt_setonechar(ttp)
+ TTYSTRUCT *ttp;
+{
+#if defined (TERMIOS_TTY_DRIVER) || defined (TERMIO_TTY_DRIVER)
+
+ /* XXX - might not want this -- it disables erase and kill processing. */
+ ttp->c_lflag &= ~ICANON;
+
+ ttp->c_lflag |= ISIG;
+# ifdef IEXTEN
+ ttp->c_lflag |= IEXTEN;
+# endif
+
+ ttp->c_iflag |= ICRNL; /* make sure we get CR->NL on input */
+ ttp->c_iflag &= ~INLCR; /* but no NL->CR */
+
+# ifdef OPOST
+ ttp->c_oflag |= OPOST;
+# endif
+# ifdef ONLCR
+ ttp->c_oflag |= ONLCR;
+# endif
+# ifdef OCRNL
+ ttp->c_oflag &= ~OCRNL;
+# endif
+# ifdef ONOCR
+ ttp->c_oflag &= ~ONOCR;
+# endif
+# ifdef ONLRET
+ ttp->c_oflag &= ~ONLRET;
+# endif
+
+ ttp->c_cc[VMIN] = 1;
+ ttp->c_cc[VTIME] = 0;
+
+#else
+
+ ttp->sg_flags |= CBREAK;
+
+#endif
+
+ return 0;
+}
+
+/* Set the tty associated with FD and TTP into one-character-at-a-time mode */
+int
+ttfd_onechar (fd, ttp)
+ int fd;
+ TTYSTRUCT *ttp;
+{
+ if (tt_setonechar(ttp) < 0)
+ return -1;
+ return (ttsetattr (fd, ttp));
+}
+
+/* Set the terminal into one-character-at-a-time mode */
+int
+ttonechar ()
+{
+ TTYSTRUCT tt;
+
+ if (ttsaved == 0)
+ return -1;
+ tt = ttin;
+ return (ttfd_onechar (0, &tt));
+}
+
+/*
+ * Change attributes in ttp so that when it is installed using
+ * ttsetattr, the terminal will be in no-echo mode.
+ */
+int
+tt_setnoecho(ttp)
+ TTYSTRUCT *ttp;
+{
+#if defined (TERMIOS_TTY_DRIVER) || defined (TERMIO_TTY_DRIVER)
+ ttp->c_lflag &= ~(ECHO|ECHOK|ECHONL);
+#else
+ ttp->sg_flags &= ~ECHO;
+#endif
+
+ return 0;
+}
+
+/* Set the tty associated with FD and TTP into no-echo mode */
+int
+ttfd_noecho (fd, ttp)
+ int fd;
+ TTYSTRUCT *ttp;
+{
+ if (tt_setnoecho (ttp) < 0)
+ return -1;
+ return (ttsetattr (fd, ttp));
+}
+
+/* Set the terminal into no-echo mode */
+int
+ttnoecho ()
+{
+ TTYSTRUCT tt;
+
+ if (ttsaved == 0)
+ return -1;
+ tt = ttin;
+ return (ttfd_noecho (0, &tt));
+}
+
+/*
+ * Change attributes in ttp so that when it is installed using
+ * ttsetattr, the terminal will be in eight-bit mode (pass8).
+ */
+int
+tt_seteightbit (ttp)
+ TTYSTRUCT *ttp;
+{
+#if defined (TERMIOS_TTY_DRIVER) || defined (TERMIO_TTY_DRIVER)
+ ttp->c_iflag &= ~ISTRIP;
+ ttp->c_cflag |= CS8;
+ ttp->c_cflag &= ~PARENB;
+#else
+ ttp->sg_flags |= ANYP;
+#endif
+
+ return 0;
+}
+
+/* Set the tty associated with FD and TTP into eight-bit mode */
+int
+ttfd_eightbit (fd, ttp)
+ int fd;
+ TTYSTRUCT *ttp;
+{
+ if (tt_seteightbit (ttp) < 0)
+ return -1;
+ return (ttsetattr (fd, ttp));
+}
+
+/* Set the terminal into eight-bit mode */
+int
+tteightbit ()
+{
+ TTYSTRUCT tt;
+
+ if (ttsaved == 0)
+ return -1;
+ tt = ttin;
+ return (ttfd_eightbit (0, &tt));
+}
+
+/*
+ * Change attributes in ttp so that when it is installed using
+ * ttsetattr, the terminal will be in non-canonical input mode.
+ */
+int
+tt_setnocanon (ttp)
+ TTYSTRUCT *ttp;
+{
+#if defined (TERMIOS_TTY_DRIVER) || defined (TERMIO_TTY_DRIVER)
+ ttp->c_lflag &= ~ICANON;
+#endif
+
+ return 0;
+}
+
+/* Set the tty associated with FD and TTP into non-canonical mode */
+int
+ttfd_nocanon (fd, ttp)
+ int fd;
+ TTYSTRUCT *ttp;
+{
+ if (tt_setnocanon (ttp) < 0)
+ return -1;
+ return (ttsetattr (fd, ttp));
+}
+
+/* Set the terminal into non-canonical mode */
+int
+ttnocanon ()
+{
+ TTYSTRUCT tt;
+
+ if (ttsaved == 0)
+ return -1;
+ tt = ttin;
+ return (ttfd_nocanon (0, &tt));
+}
+
+/*
+ * Change attributes in ttp so that when it is installed using
+ * ttsetattr, the terminal will be in cbreak, no-echo mode.
+ */
+int
+tt_setcbreak(ttp)
+ TTYSTRUCT *ttp;
+{
+ if (tt_setonechar (ttp) < 0)
+ return -1;
+ return (tt_setnoecho (ttp));
+}
+
+/* Set the terminal into cbreak (no-echo, one-character-at-a-time) mode */
+int
+ttfd_cbreak (fd, ttp)
+ int fd;
+ TTYSTRUCT *ttp;
+{
+ if (tt_setcbreak (ttp) < 0)
+ return -1;
+ return (ttsetattr (fd, ttp));
+}
+
+/* Set the terminal into cbreak (no-echo, one-character-at-a-time) mode */
+int
+ttcbreak ()
+{
+ TTYSTRUCT tt;
+
+ if (ttsaved == 0)
+ return -1;
+ tt = ttin;
+ return (ttfd_cbreak (0, &tt));
+}
/* sig.c - interface for shell signal handlers and signal initialization. */
-/* Copyright (C) 1994-2006 Free Software Foundation, Inc.
+/* Copyright (C) 1994-2007 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
right. Should it be set unconditionally? */
if (interrupt_state == 0)
ADDINTERRUPT;
-itrace("sigint_sighandler");
+
if (interrupt_immediately)
{
interrupt_immediately = 0;
#if defined (JOB_CONTROL)
set_sigchld_handler ();
stop_making_children ();
+ /* XXX - should we only do this in the parent? (as in command subst) */
pipeline_pgrp = old_pipeline_pgrp;
#endif /* JOB_CONTROL */
old_pipeline_pgrp = pipeline_pgrp;
/* Don't reset the pipeline pgrp if we're already a subshell in a pipeline. */
if ((subshell_environment & SUBSHELL_PIPE) == 0)
-{
pipeline_pgrp = shell_pgrp;
-itrace("command_substitute: set pipeline_pgrp = shell_pgrp = %d", pipeline_pgrp);
-}
cleanup_the_pipeline ();
#endif /* JOB_CONTROL */
set_sigchld_handler ();
stop_making_children ();
if (pid != 0)
-{
pipeline_pgrp = old_pipeline_pgrp;
-itrace("command_substitute: set pipeline_pgrp = %d (old_pipeline_pgrp)", pipeline_pgrp);
-}
#else
stop_making_children ();
#endif /* JOB_CONTROL */
current_command_subst_pid = pid;
last_command_exit_value = wait_for (pid);
-itrace("command_substitute: waited for pid %d: status %d", pid, last_command_exit_value);
last_command_subst_pid = pid;
last_made_pid = old_pid;
free (temp);
temp = temp1;
sindex += t_index;
- goto add_string;
+ goto add_quoted_string; /* XXX was add_string */
}
else
{
stupidly_hack_special_variables (name);
- if (entry)
- VUNSETATTR (entry, att_invisible);
-
#if 1
/* Return 1 if the assignment seems to have been performed correctly. */
if (entry == 0 || readonly_p (entry))
else
retval = 1;
ASSIGN_RETURN (retval);
+
+ if (entry && retval != 0)
+ VUNSETATTR (entry, att_invisible);
#else
+ if (entry)
+ VUNSETATTR (entry, att_invisible);
+
ASSIGN_RETURN (entry ? ((readonly_p (entry) == 0) && noassign_p (entry) == 0) : 0);
#endif
}
#if defined (JOB_CONTROL)
set_sigchld_handler ();
stop_making_children ();
+ /* XXX - should we only do this in the parent? (as in command subst) */
pipeline_pgrp = old_pipeline_pgrp;
#endif /* JOB_CONTROL */
reset_signal_handlers ();
#if defined (JOB_CONTROL)
+ /* XXX DO THIS ONLY IN PARENT ? XXX */
set_sigchld_handler ();
stop_making_children ();
- pipeline_pgrp = old_pipeline_pgrp;
+ if (pid != 0)
+ pipeline_pgrp = old_pipeline_pgrp;
#else
stop_making_children ();
#endif /* JOB_CONTROL */
t_index = zindex + 1;
temp = extract_arithmetic_subst (string, &t_index);
zindex = t_index;
+ if (temp == 0)
+ {
+ temp = savestring (string);
+ if (expanded_something)
+ *expanded_something = 0;
+ goto return0;
+ }
/* Do initial variable expansion. */
temp1 = expand_arith_string (temp, Q_DOUBLE_QUOTES);
;;
# Darwin/MacOS X
-darwin8*)
+darwin[89]*)
SHOBJ_STATUS=supported
SHLIB_STATUS=supported
SHLIB_LIBSUFF='dylib'
case "${host_os}" in
- darwin[78]*) SHOBJ_LDFLAGS=''
+ darwin[789]*) SHOBJ_LDFLAGS=''
SHLIB_XLDFLAGS='-dynamiclib -arch_only `/usr/bin/arch` -install_name $(libdir)/$@ -current_version $(SHLIB_MAJOR)$(SHLIB_MINOR) -compatibility_version $(SHLIB_MAJOR) -v'
;;
*) SHOBJ_LDFLAGS='-dynamic'
# Chet Ramey
# chet@po.cwru.edu
-# Copyright (C) 1996-2002 Free Software Foundation, Inc.
+# Copyright (C) 1996-2007 Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
SHLIB_LIBVERSION='$(SHLIB_MAJOR)$(SHLIB_MINOR).$(SHLIB_LIBSUFF)'
SHLIB_LIBSUFF='dylib'
- SHOBJ_LDFLAGS='-dynamiclib -dynamic -undefined dynamic_lookup'
+ SHOBJ_LDFLAGS='-dynamiclib -dynamic -undefined dynamic_lookup -arch_only `/usr/bin/arch`'
SHLIB_XLDFLAGS='-dynamiclib -arch_only `/usr/bin/arch` -install_name $(libdir)/$@ -current_version $(SHLIB_MAJOR)$(SHLIB_MINOR) -compatibility_version $(SHLIB_MAJOR) -v'
SHLIB_LIBS='-lncurses' # see if -lcurses works on MacOS X 10.1
SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)'
;;
-aix4.[2-9]*-*gcc*) # lightly tested by jik@cisco.com
+aix4.[2-9]*-*gcc*|aix[5-9].*-*gcc*) # lightly tested by jik@cisco.com
SHOBJ_CFLAGS=-fpic
SHOBJ_LD='ld'
SHOBJ_LDFLAGS='-bdynamic -bnoentry -bexpall'
SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)'
;;
-aix4.[2-9]*)
+aix4.[2-9]*|aix[5-9].*)
SHOBJ_CFLAGS=-K
SHOBJ_LD='ld'
SHOBJ_LDFLAGS='-bdynamic -bnoentry -bexpall'
SHOBJ_LD='${CC}'
# if you have problems linking here, moving the `-Wl,+h,$@' from
# SHLIB_XLDFLAGS to SHOBJ_LDFLAGS has been reported to work
- SHOBJ_LDFLAGS='-shared -Wl,-b -Wl,+s'
+ SHOBJ_LDFLAGS='-shared -fpic -Wl,-b -Wl,+s'
SHLIB_XLDFLAGS='-Wl,+h,$@ -Wl,+b,$(libdir)'
SHLIB_LIBSUFF='sl'