mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-26 15:23:09 +02:00
commit bash-20050210 snapshot
This commit is contained in:
+88
-1
@@ -10925,6 +10925,12 @@ configure.in
|
||||
Makefile.in
|
||||
- use $(SIZE) instead of size; set SIZE from configure
|
||||
|
||||
1/31
|
||||
----
|
||||
arrayfunc.c
|
||||
- in array_value_internal, return NULL right away if the variable's
|
||||
value is NULL, instead of passing a null string to add_string_to_list
|
||||
|
||||
2/1
|
||||
---
|
||||
jobs.h
|
||||
@@ -10943,6 +10949,7 @@ jobs.[ch]
|
||||
a job index
|
||||
- new function, reset_job_indices, called from delete_job if
|
||||
js.j_lastj or js.j_firstj are removed
|
||||
- change various functions to keep counters and stats in struct jobstats
|
||||
|
||||
pcomplete.c, builtins/common.c, builtins/{exit,fg_bg,jobs,kill,wait}.def
|
||||
- change global variables (e.g., job_slots) to struct members
|
||||
@@ -10951,7 +10958,7 @@ pcomplete.c, builtins/common.c, builtins/{exit,fg_bg,jobs,kill,wait}.def
|
||||
- use get_job_by_jid and J_JOBSTATE where appropriate
|
||||
|
||||
trap.c
|
||||
- change reset_or_restore_signal_handler to not free the trap
|
||||
- change reset_or_restore_signal_handler to not free the exit trap
|
||||
string if the function pointer is reset_signal, which is used when
|
||||
the trap strings shouldn't be freed, like in command substitution
|
||||
|
||||
@@ -10976,3 +10983,83 @@ parse.y
|
||||
(echo 6))
|
||||
|
||||
work right
|
||||
|
||||
2/8
|
||||
---
|
||||
jobs.h
|
||||
- new structs for holding status of exited background processes, as
|
||||
POSIX specifies
|
||||
- new job flag: J_ASYNC
|
||||
|
||||
jobs.c
|
||||
- new functions to manipulate struct holding status of exited
|
||||
background processes
|
||||
- new members in struct jobstats to hold pointer to last created job
|
||||
and last created asynchronous job
|
||||
- initialize js.c_childmax in initialize_job_control
|
||||
- if the `async' arg to stop_pipeline is non-null, set the J_ASYNC
|
||||
flag in the job struct
|
||||
- set js.j_last_made_job and js.j_last_asynchronous_job in
|
||||
stop_pipeline
|
||||
- new function: find_last_proc, returns the PROCESS * to the last proc
|
||||
in a job's pipeline
|
||||
- changed find_last_pid to call find_last_proc
|
||||
- change delete_job to call bgp_add on the last proc of the job being
|
||||
deleted
|
||||
- change delete_all_jobs and wait_for_background_pids to call bgp_clear
|
||||
|
||||
2/9
|
||||
---
|
||||
jobs.c
|
||||
- change wait_for_single_pid to look for pid in bgpids.list (using
|
||||
bgp_search()) if find_pipeline returns NULL
|
||||
|
||||
2/10
|
||||
----
|
||||
support/shobj-conf
|
||||
- change the solaris-gcc stanza so that it auto-selects the appropriate
|
||||
options for ld depending on which `ld' gcc says it's going to run
|
||||
|
||||
2/11
|
||||
----
|
||||
jobs.h
|
||||
- add support for PS_RECYCLED as a process state, add PRECYCLED macro
|
||||
to test it. Change PALIVE and PRUNNING macros to not count processes
|
||||
in PS_RECYCLED state
|
||||
|
||||
execute_cmd.c
|
||||
- restore use of last_pid as sentinel value; use NO_PID as sentinel
|
||||
only if RECYCLES_PIDS is defined
|
||||
|
||||
jobs.c
|
||||
- change find_job to return a pointer to the PROCESS the desired pid
|
||||
belongs to, analogous to find_pipeline returning pointer to JOB
|
||||
- change find_job callers to add extra argument
|
||||
- change running_only arguments to find_pipeline and find_job to
|
||||
alive_only, since we don't want recycled pids returned here and it
|
||||
better describes the result
|
||||
- new function find_process, calls find_pipeline and searches the
|
||||
returned pipeline for the PROCESS * describing the desired pid
|
||||
- in make_child, if fork() returns the same pid as the value of
|
||||
last_asynchronous_pid when RECYCLES_PIDS is defined, avoid pid
|
||||
aliasing by resetting last_asynchronous_pid to 1
|
||||
- use PRUNNING instead of child->running, since we, for the most
|
||||
part, don't want to consider recycled pids (e.g., in make_child())
|
||||
- call find_process instead of find_pipeline in waitchld()
|
||||
- use PEXITED(p) instead of testing p->running == PS_DONE
|
||||
- in make_child, call bgp_delete to remove a just-created pid from the
|
||||
last of saved pid statuses
|
||||
- in add_process, check whether or not pid being added is already in
|
||||
the_pipeline or the jobs list (using find_process) and mark it as
|
||||
recycled if so
|
||||
- This set of fixes mostly came from Pierre Humblet
|
||||
<pierre.humblet@ieee.org> to fix pid aliasing and reuse problems on
|
||||
cygwin
|
||||
|
||||
variables.c
|
||||
- set $_ from the environment if we get it there, set to $0 by
|
||||
default if not in env
|
||||
|
||||
doc/{bashref.texi,bash.1}
|
||||
- a couple of clarifying changes to the description of $_ based on
|
||||
comments from Glenn Morris <gmorris+mail@ast.cam.ac.uk>
|
||||
|
||||
+85
-2
@@ -10925,6 +10925,12 @@ configure.in
|
||||
Makefile.in
|
||||
- use $(SIZE) instead of size; set SIZE from configure
|
||||
|
||||
1/31
|
||||
----
|
||||
arrayfunc.c
|
||||
- in array_value_internal, return NULL right away if the variable's
|
||||
value is NULL, instead of passing a null string to add_string_to_list
|
||||
|
||||
2/1
|
||||
---
|
||||
jobs.h
|
||||
@@ -10943,6 +10949,7 @@ jobs.[ch]
|
||||
a job index
|
||||
- new function, reset_job_indices, called from delete_job if
|
||||
js.j_lastj or js.j_firstj are removed
|
||||
- change various functions to keep counters and stats in struct jobstats
|
||||
|
||||
pcomplete.c, builtins/common.c, builtins/{exit,fg_bg,jobs,kill,wait}.def
|
||||
- change global variables (e.g., job_slots) to struct members
|
||||
@@ -10951,7 +10958,7 @@ pcomplete.c, builtins/common.c, builtins/{exit,fg_bg,jobs,kill,wait}.def
|
||||
- use get_job_by_jid and J_JOBSTATE where appropriate
|
||||
|
||||
trap.c
|
||||
- change reset_or_restore_signal_handler to not free the trap
|
||||
- change reset_or_restore_signal_handler to not free the exit trap
|
||||
string if the function pointer is reset_signal, which is used when
|
||||
the trap strings shouldn't be freed, like in command substitution
|
||||
|
||||
@@ -10969,10 +10976,86 @@ jobs.c
|
||||
list if it reaches MAX_JOBS_IN_ARRAY in size
|
||||
|
||||
parse.y
|
||||
- move test for backslash-newline after pop_string in read_token so
|
||||
- move test for backslash-newline after pop_string in shell_getc so
|
||||
that things like
|
||||
|
||||
((echo 5) \
|
||||
(echo 6))
|
||||
|
||||
work right
|
||||
|
||||
2/8
|
||||
---
|
||||
jobs.h
|
||||
- new structs for holding status of exited background processes, as
|
||||
POSIX specifies
|
||||
- new job flag: J_ASYNC
|
||||
|
||||
jobs.c
|
||||
- new functions to manipulate struct holding status of exited
|
||||
background processes
|
||||
- new members in struct jobstats to hold pointer to last created job
|
||||
and last created asynchronous job
|
||||
- initialize js.c_childmax in initialize_job_control
|
||||
- if the `async' arg to stop_pipeline is non-null, set the J_ASYNC
|
||||
flag in the job struct
|
||||
- set js.j_last_made_job and js.j_last_asynchronous_job in
|
||||
stop_pipeline
|
||||
- new function: find_last_proc, returns the PROCESS * to the last proc
|
||||
in a job's pipeline
|
||||
- changed find_last_pid to call find_last_proc
|
||||
- change delete_job to call bgp_add on the last proc of the job being
|
||||
deleted
|
||||
- change delete_all_jobs and wait_for_background_pids to call bgp_clear
|
||||
|
||||
2/9
|
||||
---
|
||||
jobs.c
|
||||
- change wait_for_single_pid to look for pid in bgpids.list (using
|
||||
bgp_search()) if find_pipeline returns NULL
|
||||
|
||||
2/10
|
||||
----
|
||||
support/shobj-conf
|
||||
- change the solaris-gcc stanza so that it auto-selects the appropriate
|
||||
options for ld depending on which `ld' gcc says it's going to run
|
||||
|
||||
2/11
|
||||
----
|
||||
jobs.h
|
||||
- add support for PS_RECYCLED as a process state, add PRECYCLED macro
|
||||
to test it. Change PALIVE and PRUNNING macros to not count processes
|
||||
in PS_RECYCLED state
|
||||
|
||||
execute_cmd.c
|
||||
- restore use of last_pid as sentinel value; use NO_PID as sentinel
|
||||
only if RECYCLES_PIDS is defined
|
||||
|
||||
jobs.c
|
||||
- change find_job to return a pointer to the PROCESS the desired pid
|
||||
belongs to, analogous to find_pipeline returning pointer to JOB
|
||||
- change find_job callers to add extra argument
|
||||
- change running_only arguments to find_pipeline and find_job to
|
||||
alive_only, since we don't want recycled pids returned here and it
|
||||
better describes the result
|
||||
- new function find_process, calls find_pipeline and searches the
|
||||
returned pipeline for the PROCESS * describing the desired pid
|
||||
- in make_child, if fork() returns the same pid as the value of
|
||||
last_asynchronous_pid when RECYCLES_PIDS is defined, avoid pid
|
||||
aliasing by resetting last_asynchronous_pid to 1
|
||||
- use PRUNNING instead of child->running, since we, for the most
|
||||
part, don't want to consider recycled pids (e.g., in make_child())
|
||||
- call find_process instead of find_pipeline in waitchld()
|
||||
- use PEXITED(p) instead of testing p->running == PS_DONE
|
||||
- in make_child, call bgp_delete to remove a just-created pid from the
|
||||
last of saved pid statuses
|
||||
- in add_process, check whether or not pid being added is already in
|
||||
the_pipeline or the jobs list (using find_process) and mark it as
|
||||
recycled if so
|
||||
- This set of fixes mostly came from Pierre Humblet
|
||||
<pierre.humblet@ieee.org> to fix pid aliasing and reuse problems on
|
||||
cygwin
|
||||
|
||||
doc/{bashref.texi,bash.1}
|
||||
- a couple of clarifying changes to the description of $_ based on
|
||||
comments from Glenn Morris <gmorris+mail@ast.cam.ac.uk>
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
/* arrayfunc.c -- High-level array functions used by other parts of the shell. */
|
||||
|
||||
/* Copyright (C) 2001-2004 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2001-2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
+1
-10
@@ -385,16 +385,7 @@ assign_array_var_from_string (var, value, flags)
|
||||
|
||||
if (integer_p (var))
|
||||
this_command_name = (char *)NULL; /* no command name for errors */
|
||||
#if 0
|
||||
nval = make_variable_value (var, val, flags);
|
||||
if (var->assign_func)
|
||||
(*var->assign_func) (var, nval, ind);
|
||||
else
|
||||
array_insert (a, ind, nval);
|
||||
FREE (nval);
|
||||
#else
|
||||
bind_array_var_internal (var, ind, val, flags);
|
||||
#endif
|
||||
last_ind++;
|
||||
}
|
||||
|
||||
@@ -717,7 +708,7 @@ array_value_internal (s, quoted, allow_all, rtype)
|
||||
err_badarraysub (s);
|
||||
return ((char *)NULL);
|
||||
}
|
||||
else if (var == 0)
|
||||
else if (var == 0 || value_cell (var) == 0)
|
||||
return ((char *)NULL);
|
||||
else if (array_p (var) == 0)
|
||||
l = add_string_to_list (value_cell (var), (WORD_LIST *)NULL);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# This Makefile for building libbuiltins.a is in -*- text -*- for Emacs.
|
||||
#
|
||||
# Copyright (C) 1996-2003 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1996-2005 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
|
||||
|
||||
@@ -404,12 +404,12 @@ exec.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
|
||||
exec.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/flags.h
|
||||
exec.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
|
||||
exec.o: $(srcdir)/common.h $(topdir)/execute_cmd.h $(BASHINCDIR)/maxpath.h
|
||||
exec.o: $(topdir)/findcmd.h
|
||||
exec.o: $(topdir)/findcmd.h $(topdir)/jobs.h
|
||||
exit.o: $(topdir)/bashtypes.h
|
||||
exit.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
|
||||
exit.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
|
||||
exit.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
|
||||
exit.o: $(topdir)/subst.h $(topdir)/externs.h
|
||||
exit.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/jobs.h
|
||||
exit.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
|
||||
exit.o: $(BASHINCDIR)/maxpath.h ./builtext.h
|
||||
fc.o: $(topdir)/bashtypes.h $(BASHINCDIR)/posixstat.h
|
||||
@@ -427,6 +427,7 @@ fg_bg.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
|
||||
fg_bg.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
|
||||
fg_bg.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
|
||||
fg_bg.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
|
||||
fg_bg.o: $(topdir)/jobs.h
|
||||
getopts.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
|
||||
getopts.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
|
||||
getopts.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
|
||||
@@ -458,7 +459,7 @@ inlib.o: $(BASHINCDIR)/maxpath.h $(topdir)/subst.h $(topdir)/externs.h
|
||||
inlib.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
|
||||
jobs.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h $(topdir)/error.h
|
||||
jobs.o: $(topdir)/general.h $(topdir)/xmalloc.h $(topdir)/quit.h $(srcdir)/bashgetopt.h
|
||||
jobs.o: $(BASHINCDIR)/maxpath.h $(topdir)/externs.h
|
||||
jobs.o: $(BASHINCDIR)/maxpath.h $(topdir)/externs.h $(topdir)/jobs.h
|
||||
jobs.o: $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h $(topdir)/subst.h
|
||||
jobs.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
|
||||
kill.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h $(topdir)/error.h
|
||||
@@ -466,6 +467,7 @@ kill.o: $(topdir)/general.h $(topdir)/xmalloc.h $(topdir)/subst.h $(topdir)/exte
|
||||
kill.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
|
||||
kill.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/trap.h $(topdir)/unwind_prot.h
|
||||
kill.o: $(topdir)/variables.h $(topdir)/conftypes.h $(BASHINCDIR)/maxpath.h
|
||||
kill.o: $(topdir)/jobs.h
|
||||
let.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
|
||||
let.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
|
||||
let.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
|
||||
@@ -525,6 +527,7 @@ suspend.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
|
||||
suspend.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
|
||||
suspend.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
|
||||
suspend.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
|
||||
suspend.o: $(topdir)/jobs.h
|
||||
test.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
|
||||
test.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
|
||||
test.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
|
||||
@@ -565,6 +568,7 @@ wait.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
|
||||
wait.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
|
||||
wait.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
|
||||
wait.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
|
||||
wait.o: $(topdir)/jobs.h
|
||||
wait.o: $(BASHINCDIR)/chartypes.h
|
||||
shopt.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
|
||||
shopt.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1987-2004 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
+10
-9
@@ -514,15 +514,17 @@ get_job_by_name (name, flags)
|
||||
{
|
||||
register int i, wl, cl, match, job;
|
||||
register PROCESS *p;
|
||||
register JOB *j;
|
||||
|
||||
job = NO_JOB;
|
||||
wl = strlen (name);
|
||||
for (i = job_slots - 1; i >= 0; i--)
|
||||
for (i = js.j_jobslots - 1; i >= 0; i--)
|
||||
{
|
||||
if (jobs[i] == 0 || ((flags & JM_STOPPED) && JOBSTATE(i) != JSTOPPED))
|
||||
j = get_job_by_jid (i);
|
||||
if (j == 0 || ((flags & JM_STOPPED) && J_JOBSTATE(j) != JSTOPPED))
|
||||
continue;
|
||||
|
||||
p = jobs[i]->pipe;
|
||||
p = j->pipe;
|
||||
do
|
||||
{
|
||||
if (flags & JM_EXACT)
|
||||
@@ -553,7 +555,7 @@ get_job_by_name (name, flags)
|
||||
else
|
||||
job = i;
|
||||
}
|
||||
while (p != jobs[i]->pipe);
|
||||
while (p != j->pipe);
|
||||
}
|
||||
|
||||
return (job);
|
||||
@@ -568,7 +570,7 @@ get_job_spec (list)
|
||||
int job, jflags;
|
||||
|
||||
if (list == 0)
|
||||
return (current_job);
|
||||
return (js.j_current);
|
||||
|
||||
word = list->word->word;
|
||||
|
||||
@@ -581,20 +583,19 @@ get_job_spec (list)
|
||||
if (DIGIT (*word) && all_digits (word))
|
||||
{
|
||||
job = atoi (word);
|
||||
return (job > job_slots ? NO_JOB : job - 1);
|
||||
return (job > js.j_jobslots ? NO_JOB : job - 1);
|
||||
}
|
||||
|
||||
jflags = 0;
|
||||
switch (*word)
|
||||
{
|
||||
case 0:
|
||||
return NO_JOB;
|
||||
case '%':
|
||||
case '+':
|
||||
return (current_job);
|
||||
return (js.j_current);
|
||||
|
||||
case '-':
|
||||
return (previous_job);
|
||||
return (js.j_previous);
|
||||
|
||||
case '?': /* Substring search requested. */
|
||||
jflags |= JM_SUBSTRING;
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
This file is exit.def, from which is created exit.c.
|
||||
It implements the builtins "exit", and "logout" in Bash.
|
||||
|
||||
Copyright (C) 1987-2003 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987-2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
+1
-1
@@ -105,7 +105,7 @@ exit_or_logout (list)
|
||||
if (!exit_immediate_okay)
|
||||
{
|
||||
register int i;
|
||||
for (i = 0; i < job_slots; i++)
|
||||
for (i = 0; i < js.j_jobslots; i++)
|
||||
if (jobs[i] && STOPPED (i))
|
||||
{
|
||||
fprintf (stderr, _("There are stopped jobs.\n"));
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
This file is fg_bg.def, from which is created fg_bg.c.
|
||||
It implements the builtins "bg" and "fg" in Bash.
|
||||
|
||||
Copyright (C) 1987-2003 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987-2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
+4
-2
@@ -127,6 +127,7 @@ fg_bg (list, foreground)
|
||||
{
|
||||
sigset_t set, oset;
|
||||
int job, status, old_async_pid;
|
||||
JOB *j;
|
||||
|
||||
BLOCK_CHILD (set, oset);
|
||||
job = get_job_spec (list);
|
||||
@@ -139,7 +140,8 @@ fg_bg (list, foreground)
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/* Or if jobs[job]->pgrp == shell_pgrp. */
|
||||
j = get_job_by_jid (job);
|
||||
/* Or if j->pgrp == shell_pgrp. */
|
||||
if (IS_JOBCONTROL (job) == 0)
|
||||
{
|
||||
builtin_error (_("job %d started without job control"), job + 1);
|
||||
@@ -149,7 +151,7 @@ fg_bg (list, foreground)
|
||||
if (foreground == 0)
|
||||
{
|
||||
old_async_pid = last_asynchronous_pid;
|
||||
last_asynchronous_pid = jobs[job]->pgrp; /* As per Posix.2 5.4.2 */
|
||||
last_asynchronous_pid = j->pgrp; /* As per Posix.2 5.4.2 */
|
||||
}
|
||||
|
||||
status = start_job (job, foreground);
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
This file is jobs.def, from which is created jobs.c.
|
||||
It implements the builtins "jobs" and "disown" in Bash.
|
||||
|
||||
Copyright (C) 1987-2004 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987-2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
+4
-2
@@ -141,7 +141,7 @@ jobs_builtin (list)
|
||||
BLOCK_CHILD (set, oset);
|
||||
job = get_job_spec (list);
|
||||
|
||||
if ((job == NO_JOB) || !jobs || !jobs[job])
|
||||
if ((job == NO_JOB) || jobs == 0 || get_job_by_jid (job) == 0)
|
||||
{
|
||||
sh_badjob (list->word->word);
|
||||
any_failed++;
|
||||
@@ -162,6 +162,7 @@ execute_list_with_replacements (list)
|
||||
register WORD_LIST *l;
|
||||
int job, result;
|
||||
COMMAND *command;
|
||||
JOB *j;
|
||||
|
||||
/* First do the replacement of job specifications with pids. */
|
||||
for (l = list; l; l = l->next)
|
||||
@@ -174,8 +175,9 @@ execute_list_with_replacements (list)
|
||||
if (INVALID_JOB (job))
|
||||
continue;
|
||||
|
||||
j = get_job_by_jid (job);
|
||||
free (l->word->word);
|
||||
l->word->word = itos (jobs[job]->pgrp);
|
||||
l->word->word = itos (j->pgrp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
This file is kill.def, from which is created kill.c.
|
||||
It implements the builtin "kill" in Bash.
|
||||
|
||||
Copyright (C) 1987-2004 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987-2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
+3
-1
@@ -192,6 +192,7 @@ kill_builtin (list)
|
||||
{ /* Must be a job spec. Check it out. */
|
||||
int job;
|
||||
sigset_t set, oset;
|
||||
JOB *j;
|
||||
|
||||
BLOCK_CHILD (set, oset);
|
||||
job = get_job_spec (list);
|
||||
@@ -204,11 +205,12 @@ kill_builtin (list)
|
||||
CONTINUE_OR_FAIL;
|
||||
}
|
||||
|
||||
j = get_job_by_jid (job);
|
||||
/* Job spec used. Kill the process group. If the job was started
|
||||
without job control, then its pgrp == shell_pgrp, so we have
|
||||
to be careful. We take the pid of the first job in the pipeline
|
||||
in that case. */
|
||||
pid = IS_JOBCONTROL (job) ? jobs[job]->pgrp : jobs[job]->pipe->pid;
|
||||
pid = IS_JOBCONTROL (job) ? j->pgrp : j->pipe->pid;
|
||||
|
||||
UNBLOCK_CHILD (oset);
|
||||
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
This file is trap.def, from which is created trap.c.
|
||||
It implements the builtin "trap" in Bash.
|
||||
|
||||
Copyright (C) 1987-2004 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987-2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
@@ -214,7 +214,6 @@ showtrap (i)
|
||||
char *t, *p, *sn;
|
||||
|
||||
p = trap_list[i];
|
||||
itrace("showtrap: %d", i);
|
||||
if (p == (char *)DEFAULT_SIG)
|
||||
return;
|
||||
|
||||
@@ -243,7 +242,6 @@ display_traps (list)
|
||||
{
|
||||
int result, i;
|
||||
|
||||
itrace("trap_builtin");
|
||||
if (list == 0)
|
||||
{
|
||||
for (i = 0; i < BASH_NSIG; i++)
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
This file is wait.def, from which is created wait.c.
|
||||
It implements the builtin "wait" in Bash.
|
||||
|
||||
Copyright (C) 1987-2004 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987-2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
@@ -150,8 +150,6 @@ wait_builtin (list)
|
||||
BLOCK_CHILD (set, oset);
|
||||
job = get_job_spec (list);
|
||||
|
||||
itrace("wait_builtin: get_job_spec returns %d, js.j_current = %d", job, js.j_current);
|
||||
|
||||
if (INVALID_JOB (job))
|
||||
{
|
||||
if (job != DUP_JOB)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* command.h -- The structures used internally to represent commands, and
|
||||
the extern declarations of the functions used to create them. */
|
||||
|
||||
/* Copyright (C) 1993 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1993-2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
@@ -84,6 +84,8 @@ enum command_type { cm_for, cm_case, cm_while, cm_if, cm_simple, cm_select,
|
||||
#define W_NOEXPAND 0x04000 /* Don't expand at all -- do quote removal */
|
||||
#define W_COMPASSIGN 0x08000 /* Compound assignment */
|
||||
#define W_ASSNBLTIN 0x10000 /* word is a builtin command that takes assignments */
|
||||
#define W_ASSIGNARG 0x20000 /* word is assignment argument to command */
|
||||
#define W_HASQUOTEDNULL 0x40000 /* word contains a quoted null character */
|
||||
|
||||
/* Possible values for subshell_environment */
|
||||
#define SUBSHELL_ASYNC 0x01 /* subshell caused by `command &' */
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
/* dispose_command.c -- dispose of a COMMAND structure. */
|
||||
|
||||
/* Copyright (C) 1987,1991 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
@@ -247,6 +247,7 @@ void
|
||||
dispose_word_desc (w)
|
||||
WORD_DESC *w;
|
||||
{
|
||||
w->word = 0;
|
||||
ocache_free (wdcache, WORD_DESC, w);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
/* dispose_cmd.h -- Functions appearing in dispose_cmd.c. */
|
||||
|
||||
/* Copyright (C) 1993 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1993-2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/* dispose_cmd.h -- Functions appearing in dispose_cmd.c. */
|
||||
|
||||
/* Copyright (C) 1993 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. */
|
||||
|
||||
#if !defined (_DISPOSE_CMD_H_)
|
||||
#define _DISPOSE_CMD_H_
|
||||
|
||||
#include "stdc.h"
|
||||
|
||||
extern void dispose_command __P((COMMAND *));
|
||||
extern void dispose_word_desc __P((WORD_DESC *));
|
||||
extern void dispose_word __P((WORD_DESC *));
|
||||
extern void dispose_words __P((WORD_LIST *));
|
||||
extern void dispose_word_array __P((char **));
|
||||
extern void dispose_redirects __P((REDIRECT *));
|
||||
|
||||
#if defined (COND_COMMAND)
|
||||
extern void dispose_cond_node __P((COND_COM *));
|
||||
#endif
|
||||
|
||||
extern void dispose_function_def_contents __P((FUNCTION_DEF *));
|
||||
extern void dispose_function_def __P((FUNCTION_DEF *));
|
||||
|
||||
#endif /* !_DISPOSE_CMD_H_ */
|
||||
+7
-6
@@ -6,12 +6,12 @@
|
||||
.\" Case Western Reserve University
|
||||
.\" chet@po.CWRU.Edu
|
||||
.\"
|
||||
.\" Last Change: Tue Jan 4 17:23:59 EST 2005
|
||||
.\" Last Change: Fri Feb 11 15:43:40 EST 2005
|
||||
.\"
|
||||
.\" bash_builtins, strip all but Built-Ins section
|
||||
.if \n(zZ=1 .ig zZ
|
||||
.if \n(zY=1 .ig zY
|
||||
.TH BASH 1 "2005 Jan 4" "GNU Bash-3.1-devel"
|
||||
.TH BASH 1 "2005 Feb 11" "GNU Bash-3.1-devel"
|
||||
.\"
|
||||
.\" There's some problem with having a `@'
|
||||
.\" in a tagged paragraph with the BSD man macros.
|
||||
@@ -1205,12 +1205,13 @@ to the file name used to invoke
|
||||
as given by argument zero.
|
||||
.TP
|
||||
.B _
|
||||
At shell startup, set to the absolute file name of the shell or shell
|
||||
script being executed as passed in the argument list.
|
||||
At shell startup, set to the absolute pathname used to invoke the
|
||||
shell or shell script being executed as passed in the environment
|
||||
or argument list.
|
||||
Subsequently, expands to the last argument to the previous command,
|
||||
after expansion.
|
||||
Also set to the full file name of each command executed and placed in
|
||||
the environment exported to that command.
|
||||
Also set to the full pathname used to invoke each command executed
|
||||
and placed in the environment exported to that command.
|
||||
When checking mail, this parameter holds the name of the mail file
|
||||
currently being checked.
|
||||
.PD
|
||||
|
||||
+46
-26
@@ -1,4 +1,4 @@
|
||||
.\"
|
||||
\"
|
||||
.\" MAN PAGE COMMENTS to
|
||||
.\"
|
||||
.\" Chet Ramey
|
||||
@@ -6,12 +6,12 @@
|
||||
.\" Case Western Reserve University
|
||||
.\" chet@po.CWRU.Edu
|
||||
.\"
|
||||
.\" Last Change: Sat Nov 13 15:05:55 EST 2004
|
||||
.\" Last Change: Tue Jan 4 17:23:59 EST 2005
|
||||
.\"
|
||||
.\" bash_builtins, strip all but Built-Ins section
|
||||
.if \n(zZ=1 .ig zZ
|
||||
.if \n(zY=1 .ig zY
|
||||
.TH BASH 1 "2004 Nov 13" "GNU Bash-3.1-devel"
|
||||
.TH BASH 1 "2005 Jan 4" "GNU Bash-3.1-devel"
|
||||
.\"
|
||||
.\" There's some problem with having a `@'
|
||||
.\" in a tagged paragraph with the BSD man macros.
|
||||
@@ -51,8 +51,8 @@ bash \- GNU Bourne-Again SHell
|
||||
[options]
|
||||
[file]
|
||||
.SH COPYRIGHT
|
||||
.if n Bash is Copyright (C) 1989-2004 by the Free Software Foundation, Inc.
|
||||
.if t Bash is Copyright \(co 1989-2004 by the Free Software Foundation, Inc.
|
||||
.if n Bash is Copyright (C) 1989-2005 by the Free Software Foundation, Inc.
|
||||
.if t Bash is Copyright \(co 1989-2005 by the Free Software Foundation, Inc.
|
||||
.SH DESCRIPTION
|
||||
.B Bash
|
||||
is an \fBsh\fR-compatible command language interpreter that
|
||||
@@ -895,7 +895,11 @@ Each of the \fImetacharacters\fP listed above under
|
||||
has special meaning to the shell and must be quoted if it is to
|
||||
represent itself.
|
||||
.PP
|
||||
When the command history expansion facilities are being used, the
|
||||
When the command history expansion facilities are being used
|
||||
(see
|
||||
.SM
|
||||
.B HISTORY EXPANSION
|
||||
below), the
|
||||
\fIhistory expansion\fP character, usually \fB!\fP, must be quoted
|
||||
to prevent history expansion.
|
||||
.PP
|
||||
@@ -919,8 +923,9 @@ Enclosing characters in double quotes preserves the literal value
|
||||
of all characters within the quotes, with the exception of
|
||||
.BR $ ,
|
||||
.BR ` ,
|
||||
and
|
||||
.BR \e .
|
||||
.BR \e ,
|
||||
and, when history expansion is enabled,
|
||||
.BR ! .
|
||||
The characters
|
||||
.B $
|
||||
and
|
||||
@@ -936,8 +941,12 @@ or
|
||||
.BR <newline> .
|
||||
A double quote may be quoted within double quotes by preceding it with
|
||||
a backslash.
|
||||
When command history is being used, the double quote may not be used to
|
||||
quote the history expansion character.
|
||||
If enabled, history expansion will be performed unless an
|
||||
.B !
|
||||
appearing in double quotes is escaped using a backslash.
|
||||
The backslash preceding the
|
||||
.B !
|
||||
is not removed.
|
||||
.PP
|
||||
The special parameters
|
||||
.B *
|
||||
@@ -951,7 +960,7 @@ below).
|
||||
.PP
|
||||
Words of the form \fB$\fP'\fIstring\fP' are treated specially. The
|
||||
word expands to \fIstring\fP, with backslash-escaped characters replaced
|
||||
as specifed by the ANSI C standard. Backslash escape sequences, if
|
||||
as specified by the ANSI C standard. Backslash escape sequences, if
|
||||
present, are decoded as follows:
|
||||
.RS
|
||||
.PD 0
|
||||
@@ -2273,7 +2282,7 @@ interpreted as part of the name.
|
||||
.PP
|
||||
When braces are used, the matching ending brace is the first `\fB}\fP'
|
||||
not escaped by a backslash or within a quoted string, and not within an
|
||||
embedded arithmetic expansion, command substitution, or paramter
|
||||
embedded arithmetic expansion, command substitution, or parameter
|
||||
expansion.
|
||||
.PP
|
||||
.PD 0
|
||||
@@ -3320,19 +3329,21 @@ environment are identical between a function and its caller
|
||||
with the exception that the
|
||||
.SM
|
||||
.B DEBUG
|
||||
trap (see the description of the
|
||||
and
|
||||
.B RETURN
|
||||
traps (see the description of the
|
||||
.B trap
|
||||
builtin under
|
||||
.SM
|
||||
.B SHELL BUILTIN COMMANDS
|
||||
below) is not inherited unless the function has been given the
|
||||
below) are not inherited unless the function has been given the
|
||||
\fBtrace\fP attribute (see the description of the
|
||||
.SM
|
||||
.B declare
|
||||
builtin below) or the
|
||||
\fB\-o functrace\fP shell option has been enabled with
|
||||
the \fBset\fP builtin
|
||||
(in which case all functions inherit the \fBDEBUG\fP trap).
|
||||
(in which case all functions inherit the \fBDEBUG\fP and \fBRETURN\fP traps).
|
||||
.PP
|
||||
Variables local to the function may be declared with the
|
||||
.B local
|
||||
@@ -3471,7 +3482,7 @@ If \fIbase#\fP is omitted, then base 10 is used.
|
||||
The digits greater than 9 are represented by the lowercase letters,
|
||||
the uppercase letters, @, and _, in that order.
|
||||
If \fIbase\fP is less than or equal to 36, lowercase and uppercase
|
||||
letters may be used interchangably to represent numbers between 10
|
||||
letters may be used interchangeably to represent numbers between 10
|
||||
and 35.
|
||||
.PP
|
||||
Operators are evaluated in order of precedence. Sub-expressions in
|
||||
@@ -4594,7 +4605,7 @@ attempts word completion.
|
||||
.TP
|
||||
.B history-preserve-point
|
||||
If set to \fBon\fP, the history code attempts to place point at the
|
||||
same location on each history line retrived with \fBprevious-history\fP
|
||||
same location on each history line retrieved with \fBprevious-history\fP
|
||||
or \fBnext-history\fP.
|
||||
.TP
|
||||
.B horizontal\-scroll\-mode (Off)
|
||||
@@ -4894,6 +4905,8 @@ With an argument
|
||||
insert the \fIn\fPth word from the previous command (the words
|
||||
in the previous command begin with word 0). A negative argument
|
||||
inserts the \fIn\fPth word from the end of the previous command.
|
||||
Once the argument \fIn\fP is computed, the argument is extracted
|
||||
as if the "!\fIn\fP" history expansion had been specified.
|
||||
.TP
|
||||
.B
|
||||
yank\-last\-arg (M\-.\^, M\-_\^)
|
||||
@@ -4902,6 +4915,8 @@ the previous history entry). With an argument,
|
||||
behave exactly like \fByank\-nth\-arg\fP.
|
||||
Successive calls to \fByank\-last\-arg\fP move back through the history
|
||||
list, inserting the last argument of each line in turn.
|
||||
The history expansion facilities are used to extract the last argument,
|
||||
as if the "!$" history expansion had been specified.
|
||||
.TP
|
||||
.B shell\-expand\-line (M\-C\-e)
|
||||
Expand the line as the shell does. This
|
||||
@@ -5378,7 +5393,7 @@ special variable as delimiters.
|
||||
Shell quoting is honored.
|
||||
Each word is then expanded using
|
||||
brace expansion, tilde expansion, parameter and variable expansion,
|
||||
command substitution, arithmetic expansion, and pathname expansion,
|
||||
command substitution, and arithmetic expansion,
|
||||
as described above under
|
||||
.SM
|
||||
.BR EXPANSION .
|
||||
@@ -6420,7 +6435,8 @@ by subsequent assignment statements or unset.
|
||||
.TP
|
||||
.B \-t
|
||||
Give each \fIname\fP the \fItrace\fP attribute.
|
||||
Traced functions inherit the \fBDEBUG\fP trap from the calling shell.
|
||||
Traced functions inherit the \fBDEBUG\fP and \fBRETURN\fP traps from
|
||||
the calling shell.
|
||||
The trace attribute has no special meaning for variables.
|
||||
.TP
|
||||
.B \-x
|
||||
@@ -7479,7 +7495,10 @@ before execution resumes after the function or script.
|
||||
.TP
|
||||
\fBset\fP [\fB\-\-abefhkmnptuvxBCHP\fP] [\fB\-o\fP \fIoption\fP] [\fIarg\fP ...]
|
||||
Without options, the name and value of each shell variable are displayed
|
||||
in a format that can be reused as input.
|
||||
in a format that can be reused as input
|
||||
for setting or resetting the currently-set variables.
|
||||
Read-only variables cannot be reset.
|
||||
In \fIposix mode\fP, only shell variables are listed.
|
||||
The output is sorted according to the current locale.
|
||||
When options are specified, they set or unset shell attributes.
|
||||
Any arguments remaining after the options are processed are treated
|
||||
@@ -7652,7 +7671,7 @@ This option is disabled by default.
|
||||
Change the behavior of
|
||||
.B bash
|
||||
where the default operation differs
|
||||
from the POSIX 1003.2 standard to match the standard (\fI`posix mode\fP).
|
||||
from the POSIX 1003.2 standard to match the standard (\fIposix mode\fP).
|
||||
.TP 8
|
||||
.B privileged
|
||||
Same as
|
||||
@@ -7766,9 +7785,11 @@ follows the logical chain of directories when performing commands
|
||||
which change the current directory.
|
||||
.TP 8
|
||||
.B \-T
|
||||
If set, any trap on \fBDEBUG\fP is inherited by shell functions, command
|
||||
substitutions, and commands executed in a subshell environment.
|
||||
The \fBDEBUG\fP trap is normally not inherited in such cases.
|
||||
If set, any traps on \fBDEBUG\fP and \fBRETURN\fP are inherited by shell
|
||||
functions, command substitutions, and commands executed in a
|
||||
subshell environment.
|
||||
The \fBDEBUG\fP and \fBRETURN\fP traps are normally not inherited
|
||||
in such cases.
|
||||
.TP 8
|
||||
.B \-\-
|
||||
If no arguments follow this option, then the positional parameters are
|
||||
@@ -8531,8 +8552,7 @@ refers to a shell variable.
|
||||
Read-only variables may not be unset.
|
||||
If
|
||||
.B \-f
|
||||
is specifed,
|
||||
each
|
||||
is specified, each
|
||||
.I name
|
||||
refers to a shell function, and the function definition
|
||||
is removed.
|
||||
|
||||
+5
-4
@@ -1314,12 +1314,13 @@ to the filename used to invoke Bash, as given by argument zero.
|
||||
|
||||
@item _
|
||||
(An underscore.)
|
||||
At shell startup, set to the absolute filename of the shell or shell
|
||||
script being executed as passed in the argument list.
|
||||
At shell startup, set to the absolute pathname used to invoke the
|
||||
shell or shell script being executed as passed in the environment
|
||||
or argument list.
|
||||
Subsequently, expands to the last argument to the previous command,
|
||||
after expansion.
|
||||
Also set to the full pathname of each command executed and placed in
|
||||
the environment exported to that command.
|
||||
Also set to the full pathname used to invoke each command executed
|
||||
and placed in the environment exported to that command.
|
||||
When checking mail, this parameter holds the name of the mail file.
|
||||
@end vtable
|
||||
|
||||
|
||||
+51
-26
@@ -16,7 +16,7 @@ This is Edition @value{EDITION}, last updated @value{UPDATED},
|
||||
of @cite{The GNU Bash Reference Manual},
|
||||
for @code{Bash}, Version @value{VERSION}.
|
||||
|
||||
Copyright @copyright{} 1988-2004 Free Software Foundation, Inc.
|
||||
Copyright @copyright{} 1988-2005 Free Software Foundation, Inc.
|
||||
|
||||
Permission is granted to make and distribute verbatim copies of
|
||||
this manual provided the copyright notice and this permission notice
|
||||
@@ -457,7 +457,8 @@ parameter expansion.
|
||||
Each of the shell metacharacters (@pxref{Definitions})
|
||||
has special meaning to the shell and must be quoted if it is to
|
||||
represent itself.
|
||||
When the command history expansion facilities are being used, the
|
||||
When the command history expansion facilities are being used
|
||||
(@pxref{History Interaction}), the
|
||||
@var{history expansion} character, usually @samp{!}, must be quoted
|
||||
to prevent history expansion. @xref{Bash History Facilities}, for
|
||||
more details concerning history expansion.
|
||||
@@ -486,7 +487,8 @@ between single quotes, even when preceded by a backslash.
|
||||
|
||||
Enclosing characters in double quotes (@samp{"}) preserves the literal value
|
||||
of all characters within the quotes, with the exception of
|
||||
@samp{$}, @samp{`}, and @samp{\}.
|
||||
@samp{$}, @samp{`}, @samp{\},
|
||||
and, when history expansion is enabled, @samp{!}.
|
||||
The characters @samp{$} and @samp{`}
|
||||
retain their special meaning within double quotes (@pxref{Shell Expansions}).
|
||||
The backslash retains its special meaning only when followed by one of
|
||||
@@ -497,8 +499,9 @@ characters are removed. Backslashes preceding characters without a
|
||||
special meaning are left unmodified.
|
||||
A double quote may be quoted within double quotes by preceding it with
|
||||
a backslash.
|
||||
When command history is being used, the double quote may not be used to
|
||||
quote the history expansion character.
|
||||
If enabled, history expansion will be performed unless an @samp{!}
|
||||
appearing in double quotes is escaped using a backslash.
|
||||
The backslash preceding the @samp{!} is not removed.
|
||||
|
||||
The special parameters @samp{*} and @samp{@@} have special meaning
|
||||
when in double quotes (@pxref{Shell Parameter Expansion}).
|
||||
@@ -1118,12 +1121,12 @@ The first element of the @env{FUNCNAME} variable is set to the
|
||||
name of the function while the function is executing.
|
||||
All other aspects of the shell execution
|
||||
environment are identical between a function and its caller
|
||||
with the exception that the @env{DEBUG} trap
|
||||
below) is not inherited unless the function has been given the
|
||||
with the exception that the @env{DEBUG} and @env{RETURN} traps
|
||||
are not inherited unless the function has been given the
|
||||
@code{trace} attribute using the @code{declare} builtin or
|
||||
the @code{-o functrace} option has been enabled with
|
||||
the @code{set} builtin,
|
||||
(in which case all functions inherit the @code{DEBUG} trap).
|
||||
(in which case all functions inherit the @env{DEBUG} and @env{RETURN} traps).
|
||||
@xref{Bourne Shell Builtins}, for the description of the
|
||||
@code{trap} builtin.
|
||||
|
||||
@@ -1311,12 +1314,13 @@ to the filename used to invoke Bash, as given by argument zero.
|
||||
|
||||
@item _
|
||||
(An underscore.)
|
||||
At shell startup, set to the absolute filename of the shell or shell
|
||||
script being executed as passed in the argument list.
|
||||
At shell startup, set to the absolute file name used to invoke the
|
||||
shell or shell script being executed as passed in the environment
|
||||
or argument list.
|
||||
Subsequently, expands to the last argument to the previous command,
|
||||
after expansion.
|
||||
Also set to the full pathname of each command executed and placed in
|
||||
the environment exported to that command.
|
||||
Also set to the full pathname used to invoke each command executed
|
||||
and placed in the environment exported to that command.
|
||||
When checking mail, this parameter holds the name of the mail file.
|
||||
@end vtable
|
||||
|
||||
@@ -3283,7 +3287,8 @@ by subsequent assignment statements or unset.
|
||||
|
||||
@item -t
|
||||
Give each @var{name} the @code{trace} attribute.
|
||||
Traced functions inherit the @code{DEBUG} trap from the calling shell.
|
||||
Traced functions inherit the @code{DEBUG} and @code{RETURN} traps from
|
||||
the calling shell.
|
||||
The trace attribute has no special meaning for variables.
|
||||
|
||||
@item -x
|
||||
@@ -3912,7 +3917,10 @@ set [--abefhkmnptuvxBCHP] [-o @var{option}] [@var{argument} @dots{}]
|
||||
|
||||
If no options or arguments are supplied, @code{set} displays the names
|
||||
and values of all shell variables and functions, sorted according to the
|
||||
current locale, in a format that may be reused as input.
|
||||
current locale, in a format that may be reused as input
|
||||
for setting or resetting the currently-set variables.
|
||||
Read-only variables cannot be reset.
|
||||
In @sc{posix} mode, only shell variables are listed.
|
||||
|
||||
When options are supplied, they set or unset shell attributes.
|
||||
Options, if specified, have the following meanings:
|
||||
@@ -4123,9 +4131,11 @@ $ cd ..; pwd
|
||||
@end example
|
||||
|
||||
@item -T
|
||||
If set, any trap on @code{DEBUG} is inherited by shell functions, command
|
||||
substitutions, and commands executed in a subshell environment.
|
||||
The @code{DEBUG} trap is normally not inherited in such cases.
|
||||
If set, any trap on @code{DEBUG} and @code{RETURN} are inherited by
|
||||
shell functions, command substitutions, and commands executed
|
||||
in a subshell environment.
|
||||
The @code{DEBUG} and @code{RETURN} traps are normally not inherited
|
||||
in such cases.
|
||||
|
||||
@item --
|
||||
If no arguments follow this option, then the positional parameters are
|
||||
@@ -5444,7 +5454,7 @@ omitted, then base 10 is used.
|
||||
The digits greater than 9 are represented by the lowercase letters,
|
||||
the uppercase letters, @samp{@@}, and @samp{_}, in that order.
|
||||
If @var{base} is less than or equal to 36, lowercase and uppercase
|
||||
letters may be used interchangably to represent numbers between 10
|
||||
letters may be used interchangeably to represent numbers between 10
|
||||
and 35.
|
||||
|
||||
Operators are evaluated in order of precedence. Sub-expressions in
|
||||
@@ -6636,7 +6646,7 @@ A synonym for @code{--with-bash-malloc}.
|
||||
@item --with-installed-readline[=@var{PREFIX}]
|
||||
Define this to make Bash link with a locally-installed version of Readline
|
||||
rather than the version in @file{lib/readline}. This works only with
|
||||
Readline 4.3 and later versions. If @var{PREFIX} is @code{yes} or not
|
||||
Readline 5.0 and later versions. If @var{PREFIX} is @code{yes} or not
|
||||
supplied, @code{configure} uses the values of the make variables
|
||||
@code{includedir} and @code{libdir}, which are subdirectories of @code{prefix}
|
||||
by default, to find the installed version of Readline if it is not in
|
||||
@@ -6724,6 +6734,9 @@ Include support for matching POSIX regular expressions using the
|
||||
@samp{=~} binary operator in the @code{[[} conditional command.
|
||||
(@pxref{Conditional Constructs}).
|
||||
|
||||
@item --enable-debugger
|
||||
Include support for the bash debugger (distributed separately).
|
||||
|
||||
@item --enable-directory-stack
|
||||
Include support for a @code{csh}-like directory stack and the
|
||||
@code{pushd}, @code{popd}, and @code{dirs} builtins
|
||||
@@ -6769,17 +6782,17 @@ when used in redirections (@pxref{Redirections}).
|
||||
This enables process substitution (@pxref{Process Substitution}) if
|
||||
the operating system provides the necessary support.
|
||||
|
||||
@item --enable-progcomp
|
||||
Enable the programmable completion facilities
|
||||
(@pxref{Programmable Completion}).
|
||||
If Readline is not enabled, this option has no effect.
|
||||
|
||||
@item --enable-prompt-string-decoding
|
||||
Turn on the interpretation of a number of backslash-escaped characters
|
||||
in the @env{$PS1}, @env{$PS2}, @env{$PS3}, and @env{$PS4} prompt
|
||||
strings. See @ref{Printing a Prompt}, for a complete list of prompt
|
||||
string escape sequences.
|
||||
|
||||
@item --enable-progcomp
|
||||
Enable the programmable completion facilities
|
||||
(@pxref{Programmable Completion}).
|
||||
If Readline is not enabled, this option has no effect.
|
||||
|
||||
@item --enable-readline
|
||||
Include support for command-line editing and history with the Bash
|
||||
version of the Readline library (@pxref{Command Line Editing}).
|
||||
@@ -6793,6 +6806,16 @@ when called as @code{rbash}, enters a restricted mode. See
|
||||
Include the @code{select} builtin, which allows the generation of simple
|
||||
menus (@pxref{Conditional Constructs}).
|
||||
|
||||
@item --enable-separate-helpfiles
|
||||
Use external files for the documentation displayed by the @code{help} builtin
|
||||
instead of storing the text internally.
|
||||
|
||||
@item --enable-single-help-strings
|
||||
Store the text displayed by the @code{help} builtin as a single string for
|
||||
each help topic. This aids in translating the text to different languages.
|
||||
You may need to disable this if your compiler cannot handle very long string
|
||||
literals.
|
||||
|
||||
@item --enable-usg-echo-default
|
||||
A synonym for @code{--enable-xpg-echo-default}.
|
||||
|
||||
@@ -6801,7 +6824,7 @@ Make the @code{echo} builtin expand backslash-escaped characters by default,
|
||||
without requiring the @option{-e} option.
|
||||
This sets the default value of the @code{xpg_echo} shell option to @code{on},
|
||||
which makes the Bash @code{echo} behave more like the version specified in
|
||||
the Single Unix Specification, version 2.
|
||||
the Single Unix Specification, version 3.
|
||||
@xref{Bash Builtins}, for a description of the escape sequences that
|
||||
@code{echo} recognizes.
|
||||
|
||||
@@ -7181,7 +7204,9 @@ The @code{trap} builtin (@pxref{Bourne Shell Builtins}) allows a
|
||||
Commands specified with an @code{RETURN} trap are executed before
|
||||
execution resumes after a shell function or a shell script executed with
|
||||
@code{.} or @code{source} returns.
|
||||
The @code{RETURN} trap is not inherited by shell functions.
|
||||
The @code{RETURN} trap is not inherited by shell functions unless the
|
||||
function has been given the @code{trace} attribute or the
|
||||
@code{functrace} option has been enabled using the @code{shopt} builtin.
|
||||
|
||||
@item
|
||||
The Bash @code{type} builtin is more extensive and gives more information
|
||||
|
||||
+3
-3
@@ -2,9 +2,9 @@
|
||||
Copyright (C) 1988-2005 Free Software Foundation, Inc.
|
||||
@end ignore
|
||||
|
||||
@set LASTCHANGE Thu Dec 30 17:00:22 EST 2004
|
||||
@set LASTCHANGE Fri Feb 11 15:43:59 EST 2005
|
||||
|
||||
@set EDITION 3.1-devel
|
||||
@set VERSION 3.1-devel
|
||||
@set UPDATED 30 December 2004
|
||||
@set UPDATED-MONTH December 2004
|
||||
@set UPDATED 11 February 2005
|
||||
@set UPDATED-MONTH February 2005
|
||||
|
||||
+4
-5
@@ -1,11 +1,10 @@
|
||||
@ignore
|
||||
Copyright (C) 1988-2004 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988-2005 Free Software Foundation, Inc.
|
||||
@end ignore
|
||||
|
||||
@set LASTCHANGE Sat Nov 13 15:06:31 EST 2004
|
||||
@set LASTCHANGE Thu Dec 30 17:00:22 EST 2004
|
||||
|
||||
@set EDITION 3.1-devel
|
||||
@set VERSION 3.1-devel
|
||||
@set UPDATED 13 November 2004
|
||||
@set UPDATED-MONTH November 2004
|
||||
|
||||
@set UPDATED 30 December 2004
|
||||
@set UPDATED-MONTH December 2004
|
||||
|
||||
+6
-2
@@ -1,6 +1,6 @@
|
||||
/* execute_command.c -- Execute a COMMAND structure. */
|
||||
|
||||
/* Copyright (C) 1987-2004 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -491,6 +491,7 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
|
||||
{
|
||||
int exec_result, invert, ignore_return, was_error_trap;
|
||||
REDIRECT *my_undo_list, *exec_undo_list;
|
||||
volatile int last_pid;
|
||||
volatile int save_line_number;
|
||||
|
||||
if (command == 0 || breaking || continuing || read_but_dont_execute)
|
||||
@@ -647,7 +648,10 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
|
||||
/* We can't rely on variables retaining their values across a
|
||||
call to execute_simple_command if a longjmp occurs as the
|
||||
result of a `return' builtin. This is true for sure with gcc. */
|
||||
#if defined (RECYCLES_PIDS)
|
||||
last_made_pid = NO_PID;
|
||||
#endif
|
||||
last_pid = last_made_pid;
|
||||
was_error_trap = signal_is_trapped (ERROR_TRAP) && signal_is_ignored (ERROR_TRAP) == 0;
|
||||
|
||||
if (ignore_return && command->value.Simple)
|
||||
@@ -677,7 +681,7 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
|
||||
/* XXX - this is something to watch out for if there are problems
|
||||
when the shell is compiled without job control. */
|
||||
if (already_making_children && pipe_out == NO_PIPE &&
|
||||
last_made_pid != NO_PID)
|
||||
last_made_pid != last_pid)
|
||||
{
|
||||
stop_pipeline (asynchronous, (COMMAND *)NULL);
|
||||
|
||||
|
||||
+12
-19
@@ -491,6 +491,7 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
|
||||
{
|
||||
int exec_result, invert, ignore_return, was_error_trap;
|
||||
REDIRECT *my_undo_list, *exec_undo_list;
|
||||
volatile int last_pid;
|
||||
volatile int save_line_number;
|
||||
|
||||
if (command == 0 || breaking || continuing || read_but_dont_execute)
|
||||
@@ -647,7 +648,10 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
|
||||
/* We can't rely on variables retaining their values across a
|
||||
call to execute_simple_command if a longjmp occurs as the
|
||||
result of a `return' builtin. This is true for sure with gcc. */
|
||||
#if defined (RECYCLES_PIDS)
|
||||
last_made_pid = NO_PID;
|
||||
#endif
|
||||
last_pid = last_made_pid;
|
||||
was_error_trap = signal_is_trapped (ERROR_TRAP) && signal_is_ignored (ERROR_TRAP) == 0;
|
||||
|
||||
if (ignore_return && command->value.Simple)
|
||||
@@ -677,7 +681,7 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
|
||||
/* XXX - this is something to watch out for if there are problems
|
||||
when the shell is compiled without job control. */
|
||||
if (already_making_children && pipe_out == NO_PIPE &&
|
||||
last_made_pid != NO_PID)
|
||||
last_made_pid != last_pid)
|
||||
{
|
||||
stop_pipeline (asynchronous, (COMMAND *)NULL);
|
||||
|
||||
@@ -2741,35 +2745,20 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
|
||||
|
||||
if (dofork)
|
||||
{
|
||||
#if 0
|
||||
/* XXX memory leak if expand_words() error causes a jump_to_top_level */
|
||||
command_line = savestring (the_printed_command);
|
||||
#endif
|
||||
|
||||
/* Do this now, because execute_disk_command will do it anyway in the
|
||||
vast majority of cases. */
|
||||
maybe_make_export_env ();
|
||||
|
||||
#if 0
|
||||
if (make_child (command_line, async) == 0)
|
||||
#else
|
||||
if (make_child (savestring (the_printed_command), async) == 0)
|
||||
#endif
|
||||
{
|
||||
already_forked = 1;
|
||||
simple_command->flags |= CMD_NO_FORK;
|
||||
|
||||
#if 0
|
||||
subshell_environment = (pipe_in != NO_PIPE || pipe_out != NO_PIPE)
|
||||
? (SUBSHELL_PIPE|SUBSHELL_FORK)
|
||||
: (SUBSHELL_ASYNC|SUBSHELL_FORK);
|
||||
#else
|
||||
subshell_environment = SUBSHELL_FORK;
|
||||
if (pipe_in != NO_PIPE || pipe_out != NO_PIPE)
|
||||
subshell_environment |= SUBSHELL_PIPE;
|
||||
if (async)
|
||||
subshell_environment |= SUBSHELL_ASYNC;
|
||||
#endif
|
||||
|
||||
/* We need to do this before piping to handle some really
|
||||
pathological cases where one of the pipe file descriptors
|
||||
@@ -3187,7 +3176,13 @@ execute_function (var, words, flags, fds_to_close, async, subshell)
|
||||
restore_default_signal (ERROR_TRAP);
|
||||
}
|
||||
|
||||
/* Shell functions inherit the RETURN trap if function tracing is on
|
||||
globally or on individually for this function. */
|
||||
#if 0
|
||||
if (return_trap && ((trace_p (var) == 0) && function_trace_mode == 0))
|
||||
#else
|
||||
if (return_trap && (signal_in_progress (DEBUG_TRAP) || ((trace_p (var) == 0) && function_trace_mode == 0)))
|
||||
#endif
|
||||
{
|
||||
if (subshell == 0)
|
||||
{
|
||||
@@ -3242,12 +3237,10 @@ execute_function (var, words, flags, fds_to_close, async, subshell)
|
||||
if (return_val)
|
||||
{
|
||||
result = return_catch_value;
|
||||
#if 0
|
||||
/* Run the RETURN trap in the function's context */
|
||||
/* Run the RETURN trap in the function's context. */
|
||||
save_current = currently_executing_command;
|
||||
run_return_trap ();
|
||||
currently_executing_command = save_current;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
+573
@@ -0,0 +1,573 @@
|
||||
/* findcmd.c -- Functions to search for commands by name. */
|
||||
|
||||
/* Copyright (C) 1997 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 Inc.,
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include "chartypes.h"
|
||||
#include "bashtypes.h"
|
||||
#if !defined (_MINIX) && defined (HAVE_SYS_FILE_H)
|
||||
# include <sys/file.h>
|
||||
#endif
|
||||
#include "filecntl.h"
|
||||
#include "posixstat.h"
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "bashansi.h"
|
||||
|
||||
#include "memalloc.h"
|
||||
#include "shell.h"
|
||||
#include "flags.h"
|
||||
#include "hashlib.h"
|
||||
#include "pathexp.h"
|
||||
#include "hashcmd.h"
|
||||
#include "findcmd.h" /* matching prototypes and declarations */
|
||||
|
||||
extern int posixly_correct;
|
||||
|
||||
/* Static functions defined and used in this file. */
|
||||
static char *_find_user_command_internal __P((const char *, int));
|
||||
static char *find_user_command_internal __P((const char *, int));
|
||||
static char *find_user_command_in_path __P((const char *, char *, int));
|
||||
static char *find_in_path_element __P((const char *, char *, int, int, struct stat *));
|
||||
static char *find_absolute_program __P((const char *, int));
|
||||
|
||||
static char *get_next_path_element __P((char *, int *));
|
||||
|
||||
/* The file name which we would try to execute, except that it isn't
|
||||
possible to execute it. This is the first file that matches the
|
||||
name that we are looking for while we are searching $PATH for a
|
||||
suitable one to execute. If we cannot find a suitable executable
|
||||
file, then we use this one. */
|
||||
static char *file_to_lose_on;
|
||||
|
||||
/* Non-zero if we should stat every command found in the hash table to
|
||||
make sure it still exists. */
|
||||
int check_hashed_filenames;
|
||||
|
||||
/* DOT_FOUND_IN_SEARCH becomes non-zero when find_user_command ()
|
||||
encounters a `.' as the directory pathname while scanning the
|
||||
list of possible pathnames; i.e., if `.' comes before the directory
|
||||
containing the file of interest. */
|
||||
int dot_found_in_search = 0;
|
||||
|
||||
#define u_mode_bits(x) (((x) & 0000700) >> 6)
|
||||
#define g_mode_bits(x) (((x) & 0000070) >> 3)
|
||||
#define o_mode_bits(x) (((x) & 0000007) >> 0)
|
||||
#define X_BIT(x) ((x) & 1)
|
||||
|
||||
/* Return some flags based on information about this file.
|
||||
The EXISTS bit is non-zero if the file is found.
|
||||
The EXECABLE bit is non-zero the file is executble.
|
||||
Zero is returned if the file is not found. */
|
||||
int
|
||||
file_status (name)
|
||||
const char *name;
|
||||
{
|
||||
struct stat finfo;
|
||||
|
||||
/* Determine whether this file exists or not. */
|
||||
if (stat (name, &finfo) < 0)
|
||||
return (0);
|
||||
|
||||
/* If the file is a directory, then it is not "executable" in the
|
||||
sense of the shell. */
|
||||
if (S_ISDIR (finfo.st_mode))
|
||||
return (FS_EXISTS|FS_DIRECTORY);
|
||||
|
||||
#if defined (AFS)
|
||||
/* We have to use access(2) to determine access because AFS does not
|
||||
support Unix file system semantics. This may produce wrong
|
||||
answers for non-AFS files when ruid != euid. I hate AFS. */
|
||||
return ((access (name, X_OK) == 0) ? (FS_EXISTS|FS_EXECABLE) : FS_EXISTS);
|
||||
#else /* !AFS */
|
||||
|
||||
/* Find out if the file is actually executable. By definition, the
|
||||
only other criteria is that the file has an execute bit set that
|
||||
we can use. */
|
||||
|
||||
/* Root only requires execute permission for any of owner, group or
|
||||
others to be able to exec a file. */
|
||||
if (current_user.euid == (uid_t)0)
|
||||
{
|
||||
int bits;
|
||||
|
||||
bits = (u_mode_bits (finfo.st_mode) |
|
||||
g_mode_bits (finfo.st_mode) |
|
||||
o_mode_bits (finfo.st_mode));
|
||||
|
||||
return ((X_BIT (bits)) ? (FS_EXISTS | FS_EXECABLE) : FS_EXISTS);
|
||||
}
|
||||
|
||||
/* If we are the owner of the file, the owner execute bit applies. */
|
||||
if (current_user.euid == finfo.st_uid)
|
||||
return ((X_BIT (u_mode_bits (finfo.st_mode))) ? (FS_EXISTS | FS_EXECABLE) : FS_EXISTS);
|
||||
|
||||
/* If we are in the owning group, the group permissions apply. */
|
||||
else if (group_member (finfo.st_gid))
|
||||
return ((X_BIT (g_mode_bits (finfo.st_mode))) ? (FS_EXISTS | FS_EXECABLE) : FS_EXISTS);
|
||||
|
||||
/* Else we check whether `others' have permission to execute the file */
|
||||
else
|
||||
return ((X_BIT (o_mode_bits (finfo.st_mode))) ? (FS_EXISTS | FS_EXECABLE) : FS_EXISTS);
|
||||
#endif /* !AFS */
|
||||
}
|
||||
|
||||
/* Return non-zero if FILE exists and is executable.
|
||||
Note that this function is the definition of what an
|
||||
executable file is; do not change this unless YOU know
|
||||
what an executable file is. */
|
||||
int
|
||||
executable_file (file)
|
||||
const char *file;
|
||||
{
|
||||
int s;
|
||||
|
||||
s = file_status (file);
|
||||
return ((s & FS_EXECABLE) && ((s & FS_DIRECTORY) == 0));
|
||||
}
|
||||
|
||||
int
|
||||
is_directory (file)
|
||||
const char *file;
|
||||
{
|
||||
return (file_status (file) & FS_DIRECTORY);
|
||||
}
|
||||
|
||||
int
|
||||
executable_or_directory (file)
|
||||
const char *file;
|
||||
{
|
||||
int s;
|
||||
|
||||
s = file_status (file);
|
||||
return ((s & FS_EXECABLE) || (s & FS_DIRECTORY));
|
||||
}
|
||||
|
||||
/* Locate the executable file referenced by NAME, searching along
|
||||
the contents of the shell PATH variable. Return a new string
|
||||
which is the full pathname to the file, or NULL if the file
|
||||
couldn't be found. If a file is found that isn't executable,
|
||||
and that is the only match, then return that. */
|
||||
char *
|
||||
find_user_command (name)
|
||||
const char *name;
|
||||
{
|
||||
return (find_user_command_internal (name, FS_EXEC_PREFERRED|FS_NODIRS));
|
||||
}
|
||||
|
||||
/* Locate the file referenced by NAME, searching along the contents
|
||||
of the shell PATH variable. Return a new string which is the full
|
||||
pathname to the file, or NULL if the file couldn't be found. This
|
||||
returns the first file found. */
|
||||
char *
|
||||
find_path_file (name)
|
||||
const char *name;
|
||||
{
|
||||
return (find_user_command_internal (name, FS_EXISTS));
|
||||
}
|
||||
|
||||
static char *
|
||||
_find_user_command_internal (name, flags)
|
||||
const char *name;
|
||||
int flags;
|
||||
{
|
||||
char *path_list, *cmd;
|
||||
SHELL_VAR *var;
|
||||
|
||||
/* Search for the value of PATH in both the temporary environments and
|
||||
in the regular list of variables. */
|
||||
if (var = find_variable_internal ("PATH", 1)) /* XXX could be array? */
|
||||
path_list = value_cell (var);
|
||||
else
|
||||
path_list = (char *)NULL;
|
||||
|
||||
if (path_list == 0 || *path_list == '\0')
|
||||
return (savestring (name));
|
||||
|
||||
cmd = find_user_command_in_path (name, path_list, flags);
|
||||
|
||||
return (cmd);
|
||||
}
|
||||
|
||||
static char *
|
||||
find_user_command_internal (name, flags)
|
||||
const char *name;
|
||||
int flags;
|
||||
{
|
||||
#ifdef __WIN32__
|
||||
char *res, *dotexe;
|
||||
|
||||
dotexe = (char *)xmalloc (strlen (name) + 5);
|
||||
strcpy (dotexe, name);
|
||||
strcat (dotexe, ".exe");
|
||||
res = _find_user_command_internal (dotexe, flags);
|
||||
free (dotexe);
|
||||
if (res == 0)
|
||||
res = _find_user_command_internal (name, flags);
|
||||
return res;
|
||||
#else
|
||||
return (_find_user_command_internal (name, flags));
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Return the next element from PATH_LIST, a colon separated list of
|
||||
paths. PATH_INDEX_POINTER is the address of an index into PATH_LIST;
|
||||
the index is modified by this function.
|
||||
Return the next element of PATH_LIST or NULL if there are no more. */
|
||||
static char *
|
||||
get_next_path_element (path_list, path_index_pointer)
|
||||
char *path_list;
|
||||
int *path_index_pointer;
|
||||
{
|
||||
char *path;
|
||||
|
||||
path = extract_colon_unit (path_list, path_index_pointer);
|
||||
|
||||
if (path == 0)
|
||||
return (path);
|
||||
|
||||
if (*path == '\0')
|
||||
{
|
||||
free (path);
|
||||
path = savestring (".");
|
||||
}
|
||||
|
||||
return (path);
|
||||
}
|
||||
|
||||
/* Look for PATHNAME in $PATH. Returns either the hashed command
|
||||
corresponding to PATHNAME or the first instance of PATHNAME found
|
||||
in $PATH. Returns a newly-allocated string. */
|
||||
char *
|
||||
search_for_command (pathname)
|
||||
const char *pathname;
|
||||
{
|
||||
char *hashed_file, *command;
|
||||
int temp_path, st;
|
||||
SHELL_VAR *path;
|
||||
|
||||
hashed_file = command = (char *)NULL;
|
||||
|
||||
/* If PATH is in the temporary environment for this command, don't use the
|
||||
hash table to search for the full pathname. */
|
||||
path = find_variable_internal ("PATH", 1);
|
||||
temp_path = path && tempvar_p (path);
|
||||
if (temp_path == 0 && path)
|
||||
path = (SHELL_VAR *)NULL;
|
||||
|
||||
/* Don't waste time trying to find hashed data for a pathname
|
||||
that is already completely specified or if we're using a command-
|
||||
specific value for PATH. */
|
||||
if (path == 0 && absolute_program (pathname) == 0)
|
||||
hashed_file = phash_search (pathname);
|
||||
|
||||
/* If a command found in the hash table no longer exists, we need to
|
||||
look for it in $PATH. Thank you Posix.2. This forces us to stat
|
||||
every command found in the hash table. */
|
||||
|
||||
if (hashed_file && (posixly_correct || check_hashed_filenames))
|
||||
{
|
||||
st = file_status (hashed_file);
|
||||
if ((st ^ (FS_EXISTS | FS_EXECABLE)) != 0)
|
||||
{
|
||||
phash_remove (pathname);
|
||||
free (hashed_file);
|
||||
hashed_file = (char *)NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (hashed_file)
|
||||
command = hashed_file;
|
||||
else if (absolute_program (pathname))
|
||||
/* A command containing a slash is not looked up in PATH or saved in
|
||||
the hash table. */
|
||||
command = savestring (pathname);
|
||||
else
|
||||
{
|
||||
/* If $PATH is in the temporary environment, we've already retrieved
|
||||
it, so don't bother trying again. */
|
||||
if (temp_path)
|
||||
{
|
||||
command = find_user_command_in_path (pathname, value_cell (path),
|
||||
FS_EXEC_PREFERRED|FS_NODIRS);
|
||||
}
|
||||
else
|
||||
command = find_user_command (pathname);
|
||||
if (command && hashing_enabled && temp_path == 0)
|
||||
phash_insert ((char *)pathname, command, dot_found_in_search, 1); /* XXX fix const later */
|
||||
}
|
||||
return (command);
|
||||
}
|
||||
|
||||
char *
|
||||
user_command_matches (name, flags, state)
|
||||
const char *name;
|
||||
int flags, state;
|
||||
{
|
||||
register int i;
|
||||
int path_index, name_len;
|
||||
char *path_list, *path_element, *match;
|
||||
struct stat dotinfo;
|
||||
static char **match_list = NULL;
|
||||
static int match_list_size = 0;
|
||||
static int match_index = 0;
|
||||
|
||||
if (state == 0)
|
||||
{
|
||||
/* Create the list of matches. */
|
||||
if (match_list == 0)
|
||||
{
|
||||
match_list_size = 5;
|
||||
match_list = strvec_create (match_list_size);
|
||||
}
|
||||
|
||||
/* Clear out the old match list. */
|
||||
for (i = 0; i < match_list_size; i++)
|
||||
match_list[i] = 0;
|
||||
|
||||
/* We haven't found any files yet. */
|
||||
match_index = 0;
|
||||
|
||||
if (absolute_program (name))
|
||||
{
|
||||
match_list[0] = find_absolute_program (name, flags);
|
||||
match_list[1] = (char *)NULL;
|
||||
path_list = (char *)NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
name_len = strlen (name);
|
||||
file_to_lose_on = (char *)NULL;
|
||||
dot_found_in_search = 0;
|
||||
stat (".", &dotinfo);
|
||||
path_list = get_string_value ("PATH");
|
||||
path_index = 0;
|
||||
}
|
||||
|
||||
while (path_list && path_list[path_index])
|
||||
{
|
||||
path_element = get_next_path_element (path_list, &path_index);
|
||||
|
||||
if (path_element == 0)
|
||||
break;
|
||||
|
||||
match = find_in_path_element (name, path_element, flags, name_len, &dotinfo);
|
||||
|
||||
free (path_element);
|
||||
|
||||
if (match == 0)
|
||||
continue;
|
||||
|
||||
if (match_index + 1 == match_list_size)
|
||||
{
|
||||
match_list_size += 10;
|
||||
match_list = strvec_resize (match_list, (match_list_size + 1));
|
||||
}
|
||||
|
||||
match_list[match_index++] = match;
|
||||
match_list[match_index] = (char *)NULL;
|
||||
FREE (file_to_lose_on);
|
||||
file_to_lose_on = (char *)NULL;
|
||||
}
|
||||
|
||||
/* We haven't returned any strings yet. */
|
||||
match_index = 0;
|
||||
}
|
||||
|
||||
match = match_list[match_index];
|
||||
|
||||
if (match)
|
||||
match_index++;
|
||||
|
||||
return (match);
|
||||
}
|
||||
|
||||
static char *
|
||||
find_absolute_program (name, flags)
|
||||
const char *name;
|
||||
int flags;
|
||||
{
|
||||
int st;
|
||||
|
||||
st = file_status (name);
|
||||
|
||||
/* If the file doesn't exist, quit now. */
|
||||
if ((st & FS_EXISTS) == 0)
|
||||
return ((char *)NULL);
|
||||
|
||||
/* If we only care about whether the file exists or not, return
|
||||
this filename. Otherwise, maybe we care about whether this
|
||||
file is executable. If it is, and that is what we want, return it. */
|
||||
if ((flags & FS_EXISTS) || ((flags & FS_EXEC_ONLY) && (st & FS_EXECABLE)))
|
||||
return (savestring (name));
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static char *
|
||||
find_in_path_element (name, path, flags, name_len, dotinfop)
|
||||
const char *name;
|
||||
char *path;
|
||||
int flags, name_len;
|
||||
struct stat *dotinfop;
|
||||
{
|
||||
int status;
|
||||
char *full_path, *xpath;
|
||||
|
||||
xpath = (*path == '~') ? bash_tilde_expand (path, 0) : path;
|
||||
|
||||
/* Remember the location of "." in the path, in all its forms
|
||||
(as long as they begin with a `.', e.g. `./.') */
|
||||
if (dot_found_in_search == 0 && *xpath == '.')
|
||||
dot_found_in_search = same_file (".", xpath, dotinfop, (struct stat *)NULL);
|
||||
|
||||
full_path = sh_makepath (xpath, name, 0);
|
||||
|
||||
status = file_status (full_path);
|
||||
itrace("find_in_path_element: %s (%s) -> %d", full_path, xpath, status);
|
||||
if (xpath != path)
|
||||
free (xpath);
|
||||
|
||||
if ((status & FS_EXISTS) == 0)
|
||||
{
|
||||
free (full_path);
|
||||
return ((char *)NULL);
|
||||
}
|
||||
|
||||
/* The file exists. If the caller simply wants the first file, here it is. */
|
||||
if (flags & FS_EXISTS)
|
||||
return (full_path);
|
||||
|
||||
/* If the file is executable, then it satisfies the cases of
|
||||
EXEC_ONLY and EXEC_PREFERRED. Return this file unconditionally. */
|
||||
if ((status & FS_EXECABLE) &&
|
||||
(((flags & FS_NODIRS) == 0) || ((status & FS_DIRECTORY) == 0)))
|
||||
{
|
||||
FREE (file_to_lose_on);
|
||||
file_to_lose_on = (char *)NULL;
|
||||
return (full_path);
|
||||
}
|
||||
|
||||
/* The file is not executable, but it does exist. If we prefer
|
||||
an executable, then remember this one if it is the first one
|
||||
we have found. */
|
||||
if ((flags & FS_EXEC_PREFERRED) && file_to_lose_on == 0)
|
||||
file_to_lose_on = savestring (full_path);
|
||||
|
||||
/* If we want only executable files, or we don't want directories and
|
||||
this file is a directory, fail. */
|
||||
if ((flags & FS_EXEC_ONLY) || (flags & FS_EXEC_PREFERRED) ||
|
||||
((flags & FS_NODIRS) && (status & FS_DIRECTORY)))
|
||||
{
|
||||
free (full_path);
|
||||
return ((char *)NULL);
|
||||
}
|
||||
else
|
||||
return (full_path);
|
||||
}
|
||||
|
||||
/* This does the dirty work for find_user_command_internal () and
|
||||
user_command_matches ().
|
||||
NAME is the name of the file to search for.
|
||||
PATH_LIST is a colon separated list of directories to search.
|
||||
FLAGS contains bit fields which control the files which are eligible.
|
||||
Some values are:
|
||||
FS_EXEC_ONLY: The file must be an executable to be found.
|
||||
FS_EXEC_PREFERRED: If we can't find an executable, then the
|
||||
the first file matching NAME will do.
|
||||
FS_EXISTS: The first file found will do.
|
||||
FS_NODIRS: Don't find any directories.
|
||||
*/
|
||||
static char *
|
||||
find_user_command_in_path (name, path_list, flags)
|
||||
const char *name;
|
||||
char *path_list;
|
||||
int flags;
|
||||
{
|
||||
char *full_path, *path;
|
||||
int path_index, name_len;
|
||||
struct stat dotinfo;
|
||||
|
||||
/* We haven't started looking, so we certainly haven't seen
|
||||
a `.' as the directory path yet. */
|
||||
dot_found_in_search = 0;
|
||||
|
||||
if (absolute_program (name))
|
||||
{
|
||||
full_path = find_absolute_program (name, flags);
|
||||
return (full_path);
|
||||
}
|
||||
|
||||
if (path_list == 0 || *path_list == '\0')
|
||||
return (savestring (name)); /* XXX */
|
||||
|
||||
file_to_lose_on = (char *)NULL;
|
||||
name_len = strlen (name);
|
||||
stat (".", &dotinfo);
|
||||
path_index = 0;
|
||||
|
||||
while (path_list[path_index])
|
||||
{
|
||||
/* Allow the user to interrupt out of a lengthy path search. */
|
||||
QUIT;
|
||||
|
||||
path = get_next_path_element (path_list, &path_index);
|
||||
if (path == 0)
|
||||
break;
|
||||
|
||||
/* Side effects: sets dot_found_in_search, possibly sets
|
||||
file_to_lose_on. */
|
||||
full_path = find_in_path_element (name, path, flags, name_len, &dotinfo);
|
||||
free (path);
|
||||
|
||||
/* This should really be in find_in_path_element, but there isn't the
|
||||
right combination of flags. */
|
||||
if (full_path && is_directory (full_path))
|
||||
{
|
||||
free (full_path);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (full_path)
|
||||
{
|
||||
FREE (file_to_lose_on);
|
||||
return (full_path);
|
||||
}
|
||||
}
|
||||
|
||||
/* We didn't find exactly what the user was looking for. Return
|
||||
the contents of FILE_TO_LOSE_ON which is NULL when the search
|
||||
required an executable, or non-NULL if a file was found and the
|
||||
search would accept a non-executable as a last resort. If the
|
||||
caller specified FS_NODIRS, and file_to_lose_on is a directory,
|
||||
return NULL. */
|
||||
if (file_to_lose_on && (flags & FS_NODIRS) && is_directory (file_to_lose_on))
|
||||
{
|
||||
free (file_to_lose_on);
|
||||
file_to_lose_on = (char *)NULL;
|
||||
}
|
||||
|
||||
return (file_to_lose_on);
|
||||
}
|
||||
@@ -160,7 +160,9 @@ extern procenv_t wait_intr_buf;
|
||||
extern int wait_signal_received;
|
||||
extern WORD_LIST *subst_assign_varlist;
|
||||
|
||||
struct jobstats js = { -1L, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NO_JOB, NO_JOB };
|
||||
struct jobstats js = { -1L, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NO_JOB, NO_JOB, 0, 0 };
|
||||
|
||||
struct bgpids bgpids = { 0, 0, 0 };
|
||||
|
||||
/* The array of known jobs. */
|
||||
JOB **jobs = (JOB **)NULL;
|
||||
@@ -234,12 +236,14 @@ static sighandler sigstop_sighandler __P((int));
|
||||
static int waitchld __P((pid_t, int));
|
||||
|
||||
static PROCESS *find_pipeline __P((pid_t, int, int *));
|
||||
static PROCESS *find_process __P((pid_t, int, int *));
|
||||
|
||||
static char *current_working_directory __P((void));
|
||||
static char *job_working_directory __P((void));
|
||||
static char *j_strsignal __P((int));
|
||||
static char *printable_job_status __P((int, PROCESS *, int));
|
||||
|
||||
static PROCESS *find_last_proc __P((int, int));
|
||||
static pid_t find_last_pid __P((int, int));
|
||||
|
||||
static int set_new_line_discipline __P((int));
|
||||
@@ -247,7 +251,7 @@ static int map_over_jobs __P((sh_job_map_func_t *, int, int));
|
||||
static int job_last_stopped __P((int));
|
||||
static int job_last_running __P((int));
|
||||
static int most_recent_job_in_state __P((int, JOB_STATE));
|
||||
static int find_job __P((pid_t, int));
|
||||
static int find_job __P((pid_t, int, PROCESS **));
|
||||
static int print_job __P((JOB *, int, int, int));
|
||||
static int process_exit_status __P((WAIT));
|
||||
static int process_exit_signal __P((WAIT));
|
||||
@@ -279,6 +283,13 @@ static void pipe_read __P((int *));
|
||||
static void pipe_close __P((int *));
|
||||
#endif
|
||||
|
||||
static struct pidstat *bgp_alloc __P((pid_t, int));
|
||||
static struct pidstat *bgp_add __P((pid_t, int));
|
||||
static int bgp_delete __P((pid_t));
|
||||
static void bgp_clear __P((void));
|
||||
static int bgp_search __P((pid_t));
|
||||
static void bgp_prune __P((void));
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
static int *pstatuses; /* list of pipeline statuses */
|
||||
static int statsize;
|
||||
@@ -535,7 +546,7 @@ stop_pipeline (async, deferred)
|
||||
if (the_pipeline)
|
||||
{
|
||||
register PROCESS *p;
|
||||
int any_alive, any_stopped, n;
|
||||
int any_running, any_stopped, n;
|
||||
|
||||
newjob = (JOB *)xmalloc (sizeof (JOB));
|
||||
|
||||
@@ -559,16 +570,16 @@ stop_pipeline (async, deferred)
|
||||
|
||||
/* Set the state of this pipeline. */
|
||||
p = newjob->pipe;
|
||||
any_alive = any_stopped = 0;
|
||||
any_running = any_stopped = 0;
|
||||
do
|
||||
{
|
||||
any_alive |= p->running;
|
||||
any_stopped |= WIFSTOPPED (p->status);
|
||||
any_running |= PRUNNING (p);
|
||||
any_stopped |= PSTOPPED (p);
|
||||
p = p->next;
|
||||
}
|
||||
while (p != newjob->pipe);
|
||||
|
||||
newjob->state = any_alive ? JRUNNING : (any_stopped ? JSTOPPED : JDEAD);
|
||||
newjob->state = any_running ? JRUNNING : (any_stopped ? JSTOPPED : JDEAD);
|
||||
newjob->wd = job_working_directory ();
|
||||
newjob->deferred = deferred;
|
||||
|
||||
@@ -591,10 +602,17 @@ stop_pipeline (async, deferred)
|
||||
else
|
||||
newjob = (JOB *)NULL;
|
||||
|
||||
if (newjob)
|
||||
js.j_lastmade = newjob;
|
||||
|
||||
if (async)
|
||||
{
|
||||
if (newjob)
|
||||
newjob->flags &= ~J_FOREGROUND;
|
||||
{
|
||||
newjob->flags &= ~J_FOREGROUND;
|
||||
newjob->flags |= J_ASYNC;
|
||||
js.j_lastasync = newjob;
|
||||
}
|
||||
reset_current ();
|
||||
}
|
||||
else
|
||||
@@ -621,9 +639,132 @@ stop_pipeline (async, deferred)
|
||||
return (js.j_current);
|
||||
}
|
||||
|
||||
/* Functions to manage the list of exited background pids whose status has
|
||||
been saved. */
|
||||
|
||||
static struct pidstat *
|
||||
bgp_alloc (pid, status)
|
||||
pid_t pid;
|
||||
int status;
|
||||
{
|
||||
struct pidstat *ps;
|
||||
|
||||
ps = (struct pidstat *)xmalloc (sizeof (struct pidstat));
|
||||
ps->pid = pid;
|
||||
ps->status = status;
|
||||
ps->next = (struct pidstat *)0;
|
||||
return ps;
|
||||
}
|
||||
|
||||
static struct pidstat *
|
||||
bgp_add (pid, status)
|
||||
pid_t pid;
|
||||
int status;
|
||||
{
|
||||
struct pidstat *ps;
|
||||
|
||||
ps = bgp_alloc (pid, status);
|
||||
|
||||
if (bgpids.list == 0)
|
||||
{
|
||||
bgpids.list = bgpids.end = ps;
|
||||
bgpids.npid = 0; /* just to make sure */
|
||||
}
|
||||
else
|
||||
{
|
||||
bgpids.end->next = ps;
|
||||
bgpids.end = ps;
|
||||
}
|
||||
bgpids.npid++;
|
||||
|
||||
if (bgpids.npid > js.c_childmax)
|
||||
bgp_prune ();
|
||||
|
||||
return ps;
|
||||
}
|
||||
|
||||
static int
|
||||
bgp_delete (pid)
|
||||
pid_t pid;
|
||||
{
|
||||
struct pidstat *prev, *p;
|
||||
|
||||
for (prev = p = bgpids.list; p; prev = p, p = p->next)
|
||||
if (p->pid == pid)
|
||||
{
|
||||
prev->next = p->next; /* remove from list */
|
||||
break;
|
||||
}
|
||||
|
||||
if (p == 0)
|
||||
return 0; /* not found */
|
||||
|
||||
itrace("bgp_delete: deleting %d", pid);
|
||||
|
||||
/* Housekeeping in the border cases. */
|
||||
if (p == bgpids.list)
|
||||
bgpids.list = bgpids.list->next;
|
||||
else if (p == bgpids.end)
|
||||
bgpids.end = prev;
|
||||
|
||||
bgpids.npid--;
|
||||
if (bgpids.npid == 0)
|
||||
bgpids.list = bgpids.end = 0;
|
||||
else if (bgpids.npid == 1)
|
||||
bgpids.end = bgpids.list; /* just to make sure */
|
||||
|
||||
free (p);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Clear out the list of saved statuses */
|
||||
static void
|
||||
bgp_clear ()
|
||||
{
|
||||
struct pidstat *ps, *p;
|
||||
|
||||
for (ps = bgpids.list; ps; )
|
||||
{
|
||||
p = ps;
|
||||
ps = ps->next;
|
||||
free (p);
|
||||
}
|
||||
bgpids.list = bgpids.end = 0;
|
||||
bgpids.npid = 0;
|
||||
}
|
||||
|
||||
/* Search for PID in the list of saved background pids; return its status if
|
||||
found. If not found, return -1. */
|
||||
static int
|
||||
bgp_search (pid)
|
||||
pid_t pid;
|
||||
{
|
||||
struct pidstat *ps;
|
||||
|
||||
for (ps = bgpids.list ; ps; ps = ps->next)
|
||||
if (ps->pid == pid)
|
||||
return ps->status;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
bgp_prune ()
|
||||
{
|
||||
struct pidstat *ps, *p;
|
||||
|
||||
while (bgpids.npid > js.c_childmax)
|
||||
{
|
||||
ps = bgpids.list;
|
||||
bgpids.list = bgpids.list->next;
|
||||
free (ps);
|
||||
bgpids.npid--;
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset the values of js.j_lastj and js.j_firstj after one or both have
|
||||
been deleted. The caller should check whether js.j_njobs is 0 before
|
||||
calling this. */
|
||||
calling this. This wraps around, but the rest of the code does not. At
|
||||
this point, it should not matter. */
|
||||
static void
|
||||
reset_job_indices ()
|
||||
{
|
||||
@@ -759,20 +900,30 @@ delete_job (job_index, warn_stopped)
|
||||
int job_index, warn_stopped;
|
||||
{
|
||||
register JOB *temp;
|
||||
int ndel;
|
||||
PROCESS *proc;
|
||||
int ndel, status;
|
||||
pid_t pid;
|
||||
|
||||
if (js.j_jobslots == 0 || jobs_list_frozen)
|
||||
return;
|
||||
|
||||
if (warn_stopped && subshell_environment == 0 && STOPPED (job_index))
|
||||
internal_warning (_("deleting stopped job %d with process group %ld"), job_index+1, (long)jobs[job_index]->pgrp);
|
||||
|
||||
temp = jobs[job_index];
|
||||
if (job_index == js.j_current || job_index == js.j_previous)
|
||||
reset_current ();
|
||||
|
||||
proc = find_last_proc (job_index, 0);
|
||||
/* Could do this just for J_ASYNC jobs, but we save all. */
|
||||
bgp_add (proc->pid, process_exit_status (proc->status));
|
||||
|
||||
jobs[job_index] = (JOB *)NULL;
|
||||
|
||||
if (temp == js.j_lastmade)
|
||||
js.j_lastmade = 0;
|
||||
else if (temp == js.j_lastasync)
|
||||
js.j_lastasync = 0;
|
||||
|
||||
free (temp->wd);
|
||||
ndel = discard_pipeline (temp->pipe);
|
||||
|
||||
@@ -844,6 +995,21 @@ add_process (name, pid)
|
||||
{
|
||||
PROCESS *t, *p;
|
||||
|
||||
#if defined (RECYCLES_PIDS)
|
||||
int j;
|
||||
p = find_process (pid, 0, &j);
|
||||
if (p)
|
||||
{
|
||||
# ifdef DEBUG
|
||||
if (j == NO_JOB)
|
||||
internal_warning ("add_process: process %5ld (%s) in the_pipeline", (long)p->pid, p->command);
|
||||
# endif
|
||||
if (PALIVE (p))
|
||||
internal_warning ("add_process: pid %5ld (%s) marked as still alive", (long)p->pid, p->command);
|
||||
p->running = PS_RECYCLED; /* mark as recycled */
|
||||
}
|
||||
#endif
|
||||
|
||||
t = (PROCESS *)xmalloc (sizeof (PROCESS));
|
||||
t->next = the_pipeline;
|
||||
t->pid = pid;
|
||||
@@ -993,15 +1159,16 @@ kill_current_pipeline ()
|
||||
}
|
||||
|
||||
/* Return the pipeline that PID belongs to. Note that the pipeline
|
||||
doesn't have to belong to a job. Must be called with SIGCHLD blocked. */
|
||||
doesn't have to belong to a job. Must be called with SIGCHLD blocked.
|
||||
If JOBP is non-null, return the index of the job containing PID. */
|
||||
static PROCESS *
|
||||
find_pipeline (pid, running_only, jobp)
|
||||
find_pipeline (pid, alive_only, jobp)
|
||||
pid_t pid;
|
||||
int running_only;
|
||||
int alive_only;
|
||||
int *jobp; /* index into jobs list or NO_JOB */
|
||||
{
|
||||
int job;
|
||||
register PROCESS *p;
|
||||
PROCESS *p;
|
||||
|
||||
/* See if this process is in the pipeline that we are building. */
|
||||
if (jobp)
|
||||
@@ -1011,33 +1178,48 @@ find_pipeline (pid, running_only, jobp)
|
||||
p = the_pipeline;
|
||||
do
|
||||
{
|
||||
/* Return it if we found it. */
|
||||
if (p->pid == pid)
|
||||
{
|
||||
if ((running_only && PALIVE(p)) || (running_only == 0))
|
||||
return (p);
|
||||
}
|
||||
/* Return it if we found it. Don't ever return a recycled pid. */
|
||||
if (p->pid == pid && ((alive_only == 0 && PRECYCLED(p) == 0) || PALIVE(p)))
|
||||
return (p);
|
||||
|
||||
p = p->next;
|
||||
}
|
||||
while (p != the_pipeline);
|
||||
}
|
||||
|
||||
job = find_job (pid, running_only);
|
||||
job = find_job (pid, alive_only, &p);
|
||||
if (jobp)
|
||||
*jobp = job;
|
||||
return (job == NO_JOB) ? (PROCESS *)NULL : jobs[job]->pipe;
|
||||
}
|
||||
|
||||
/* Return the PROCESS * describing PID. If JOBP is non-null return the index
|
||||
into the jobs array of the job containing PID. Must be called with
|
||||
SIGCHLD blocked. */
|
||||
static PROCESS *
|
||||
find_process (pid, alive_only, jobp)
|
||||
pid_t pid;
|
||||
int alive_only;
|
||||
int *jobp; /* index into jobs list or NO_JOB */
|
||||
{
|
||||
PROCESS *p;
|
||||
|
||||
p = find_pipeline (pid, alive_only, jobp);
|
||||
while (p && p->pid != pid)
|
||||
p = p->next;
|
||||
return p;
|
||||
}
|
||||
|
||||
/* Return the job index that PID belongs to, or NO_JOB if it doesn't
|
||||
belong to any job. Must be called with SIGCHLD blocked. */
|
||||
static int
|
||||
find_job (pid, running_only)
|
||||
find_job (pid, alive_only, procp)
|
||||
pid_t pid;
|
||||
int running_only;
|
||||
int alive_only;
|
||||
PROCESS **procp;
|
||||
{
|
||||
register int i;
|
||||
register PROCESS *p;
|
||||
PROCESS *p;
|
||||
|
||||
/* XXX could use js.j_firstj here */
|
||||
for (i = 0; i < js.j_jobslots; i++)
|
||||
@@ -1050,10 +1232,11 @@ if (i < js.j_firstj && jobs[i])
|
||||
|
||||
do
|
||||
{
|
||||
if (p->pid == pid)
|
||||
if (p->pid == pid && ((alive_only == 0 && PRECYCLED(p) == 0) || PALIVE(p)))
|
||||
{
|
||||
if ((running_only && PALIVE(p)) || (running_only == 0))
|
||||
return (i);
|
||||
if (procp)
|
||||
*procp = p;
|
||||
return (i);
|
||||
}
|
||||
|
||||
p = p->next;
|
||||
@@ -1078,7 +1261,7 @@ get_job_by_pid (pid, block)
|
||||
if (block)
|
||||
BLOCK_CHILD (set, oset);
|
||||
|
||||
job = find_job (pid, 0);
|
||||
job = find_job (pid, 0, NULL);
|
||||
|
||||
if (block)
|
||||
UNBLOCK_CHILD (oset);
|
||||
@@ -1096,7 +1279,7 @@ describe_pid (pid)
|
||||
|
||||
BLOCK_CHILD (set, oset);
|
||||
|
||||
job = find_job (pid, 0);
|
||||
job = find_job (pid, 0, NULL);
|
||||
|
||||
if (job != NO_JOB)
|
||||
fprintf (stderr, "[%d] %ld\n", job + 1, (long)pid);
|
||||
@@ -1498,7 +1681,12 @@ make_child (command, async_p)
|
||||
#endif /* PGRP_PIPE */
|
||||
|
||||
if (async_p)
|
||||
last_asynchronous_pid = getpid ();
|
||||
last_asynchronous_pid = mypid;
|
||||
#if defined (RECYCLES_PIDS)
|
||||
else if (last_asynchronous_pid == mypid)
|
||||
/* Avoid pid aliasing. 1 seems like a safe, unusual pid value. */
|
||||
last_asynchronous_pid = 1;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1532,6 +1720,18 @@ make_child (command, async_p)
|
||||
|
||||
if (async_p)
|
||||
last_asynchronous_pid = pid;
|
||||
#if defined (RECYCLES_PIDS)
|
||||
else if (last_asynchronous_pid == pid)
|
||||
/* Avoid pid aliasing. 1 seems like a safe, unusual pid value. */
|
||||
last_asynchronous_pid = 1;
|
||||
#endif
|
||||
|
||||
#if !defined (RECYCLES_PIDS)
|
||||
/* Only check for saved status if we've saved more than CHILD_MAX
|
||||
statuses, unless the system recycles pids. */
|
||||
if ((js.c_reaped + bgpids.npid) >= js.c_childmax)
|
||||
#endif
|
||||
bgp_delete (pid); /* new process, discard any saved status */
|
||||
|
||||
last_made_pid = pid;
|
||||
|
||||
@@ -1695,11 +1895,11 @@ set_tty_state ()
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Given an index into the jobs array JOB, return the pid of the last
|
||||
/* Given an index into the jobs array JOB, return the PROCESS struct of the last
|
||||
process in that job's pipeline. This is the one whose exit status
|
||||
counts. Must be called with SIGCHLD blocked or queued. */
|
||||
static pid_t
|
||||
find_last_pid (job, block)
|
||||
static PROCESS *
|
||||
find_last_proc (job, block)
|
||||
int job;
|
||||
int block;
|
||||
{
|
||||
@@ -1716,9 +1916,21 @@ find_last_pid (job, block)
|
||||
if (block)
|
||||
UNBLOCK_CHILD (oset);
|
||||
|
||||
return (p->pid);
|
||||
return (p);
|
||||
}
|
||||
|
||||
static pid_t
|
||||
find_last_pid (job, block)
|
||||
int job;
|
||||
int block;
|
||||
{
|
||||
PROCESS *p;
|
||||
|
||||
p = find_last_proc (job, block);
|
||||
/* Possible race condition here. */
|
||||
return p->pid;
|
||||
}
|
||||
|
||||
/* Wait for a particular child of the shell to finish executing.
|
||||
This low-level function prints an error message if PID is not
|
||||
a child of this shell. It returns -1 if it fails, or whatever
|
||||
@@ -1736,6 +1948,13 @@ wait_for_single_pid (pid)
|
||||
child = find_pipeline (pid, 0, (int *)NULL);
|
||||
UNBLOCK_CHILD (oset);
|
||||
|
||||
if (child == 0)
|
||||
{
|
||||
r = bgp_search (pid);
|
||||
if (r >= 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (child == 0)
|
||||
{
|
||||
internal_error (_("wait: pid %ld is not a child of this shell"), (long)pid);
|
||||
@@ -1747,7 +1966,7 @@ wait_for_single_pid (pid)
|
||||
/* POSIX.2: if we just waited for a job, we can remove it from the jobs
|
||||
table. */
|
||||
BLOCK_CHILD (set, oset);
|
||||
job = find_job (pid, 0);
|
||||
job = find_job (pid, 0, NULL);
|
||||
if (job != NO_JOB && jobs[job] && DEADJOB (job))
|
||||
jobs[job]->flags |= J_NOTIFIED;
|
||||
UNBLOCK_CHILD (oset);
|
||||
@@ -1802,6 +2021,7 @@ if (i < js.j_firstj && jobs[i])
|
||||
`wait' is called with no arguments. */
|
||||
mark_dead_jobs_as_notified (1);
|
||||
cleanup_dead_jobs ();
|
||||
bgp_clear ();
|
||||
}
|
||||
|
||||
/* Make OLD_SIGINT_HANDLER the SIGINT signal handler. */
|
||||
@@ -1985,13 +2205,13 @@ wait_for (pid)
|
||||
We check for JDEAD in case the job state has been set by waitchld
|
||||
after receipt of a SIGCHLD. */
|
||||
if (job == NO_JOB)
|
||||
job = find_job (pid, 0);
|
||||
job = find_job (pid, 0, NULL);
|
||||
|
||||
/* waitchld() takes care of setting the state of the job. If the job
|
||||
has already exited before this is called, sigchld_handler will have
|
||||
called waitchld and the state will be set to JDEAD. */
|
||||
|
||||
if (child->running || (job != NO_JOB && RUNNING (job)))
|
||||
if (PRUNNING(child) || (job != NO_JOB && RUNNING (job)))
|
||||
{
|
||||
#if defined (WAITPID_BROKEN) /* SCOv4 */
|
||||
sigset_t suspend_set;
|
||||
@@ -2048,7 +2268,7 @@ wait_for (pid)
|
||||
if (interactive && job_control == 0)
|
||||
QUIT;
|
||||
}
|
||||
while (child->running || (job != NO_JOB && RUNNING (job)));
|
||||
while (PRUNNING (child) || (job != NO_JOB && RUNNING (job)));
|
||||
|
||||
/* The exit state of the command is either the termination state of the
|
||||
child, or the termination state of the job. If a job, the status
|
||||
@@ -2528,8 +2748,11 @@ kill_pid (pid, sig, group)
|
||||
|
||||
do
|
||||
{
|
||||
if (PALIVE (p) == 0)
|
||||
continue; /* avoid pid recycling problems */
|
||||
|
||||
kill (p->pid, sig);
|
||||
if (p->running == PS_DONE && (sig == SIGTERM || sig == SIGHUP))
|
||||
if (PEXITED (p) && (sig == SIGTERM || sig == SIGHUP))
|
||||
kill (p->pid, SIGCONT);
|
||||
p = p->next;
|
||||
}
|
||||
@@ -2636,7 +2859,7 @@ waitchld (wpid, block)
|
||||
children_exited++;
|
||||
|
||||
/* Locate our PROCESS for this pid. */
|
||||
child = find_pipeline (pid, 1, &job); /* want running procs only */
|
||||
child = find_process (pid, 1, &job); /* want living procs only */
|
||||
|
||||
/* It is not an error to have a child terminate that we did
|
||||
not have a record of. This child could have been part of
|
||||
@@ -2645,14 +2868,11 @@ waitchld (wpid, block)
|
||||
if (child == 0)
|
||||
continue;
|
||||
|
||||
while (child->pid != pid)
|
||||
child = child->next;
|
||||
|
||||
/* Remember status, and whether or not the process is running. */
|
||||
child->status = status;
|
||||
child->running = WIFCONTINUED(status) ? PS_RUNNING : PS_DONE;
|
||||
|
||||
if (child->running == PS_DONE)
|
||||
if (PEXITED (child))
|
||||
{
|
||||
js.c_totreaped++;
|
||||
if (job != NO_JOB)
|
||||
@@ -2723,8 +2943,13 @@ set_job_status_and_cleanup (job)
|
||||
job_state = any_stopped = any_tstped = 0;
|
||||
do
|
||||
{
|
||||
job_state |= child->running;
|
||||
if (child->running == PS_DONE && (WIFSTOPPED (child->status)))
|
||||
job_state |= PRUNNING (child);
|
||||
#if 0
|
||||
if (PEXITED (child) && (WIFSTOPPED (child->status)))
|
||||
#else
|
||||
/* Only checking for WIFSTOPPED now, not for PS_DONE */
|
||||
if (PSTOPPED (child))
|
||||
#endif
|
||||
{
|
||||
any_stopped = 1;
|
||||
any_tstped |= interactive && job_control &&
|
||||
@@ -3181,6 +3406,11 @@ initialize_job_control (force)
|
||||
if (interactive)
|
||||
get_tty_state ();
|
||||
|
||||
if (js.c_childmax < 0)
|
||||
js.c_childmax = getmaxchild ();
|
||||
if (js.c_childmax < 0)
|
||||
js.c_childmax = DEFAULT_CHILD_MAX;
|
||||
|
||||
return job_control;
|
||||
}
|
||||
|
||||
@@ -3430,6 +3660,9 @@ if (i < js.j_firstj && jobs[i])
|
||||
}
|
||||
}
|
||||
|
||||
if (running_only == 0)
|
||||
bgp_clear ();
|
||||
|
||||
UNBLOCK_CHILD (oset);
|
||||
}
|
||||
|
||||
@@ -3528,7 +3761,10 @@ mark_dead_jobs_as_notified (force)
|
||||
}
|
||||
|
||||
/* Mark enough dead jobs as notified to keep CHILD_MAX processes left in the
|
||||
array with the corresponding not marked as notified. */
|
||||
array with the corresponding not marked as notified. This is a better
|
||||
way to avoid pid aliasing and reuse problems than keeping the POSIX-
|
||||
mandated CHILD_MAX jobs around. delete_job() takes care of keeping the
|
||||
bgpids list regulated. */
|
||||
|
||||
/* Count the number of dead jobs */
|
||||
/* XXX could use js.j_firstj here */
|
||||
@@ -3543,10 +3779,12 @@ if (i < js.j_firstj && jobs[i])
|
||||
}
|
||||
}
|
||||
|
||||
if (ndeadproc != js.c_reaped)
|
||||
itrace("mark_dead_jobs_as_notified: ndeadproc (%d) != js.c_reaped (%d)", ndeadproc, js.c_reaped);
|
||||
if (ndead != js.j_ndead)
|
||||
itrace("mark_dead_jobs_as_notified: ndead (%d) != js.j_ndead (%d)", ndead, js.j_ndead);
|
||||
#ifdef DEBUG
|
||||
if (ndeadproc != js.c_reaped)
|
||||
itrace("mark_dead_jobs_as_notified: ndeadproc (%d) != js.c_reaped (%d)", ndeadproc, js.c_reaped);
|
||||
if (ndead != js.j_ndead)
|
||||
itrace("mark_dead_jobs_as_notified: ndead (%d) != js.j_ndead (%d)", ndead, js.j_ndead);
|
||||
#endif
|
||||
|
||||
if (js.c_childmax < 0)
|
||||
js.c_childmax = getmaxchild ();
|
||||
@@ -3561,6 +3799,10 @@ if (ndead != js.j_ndead)
|
||||
return;
|
||||
}
|
||||
|
||||
#if 0
|
||||
itrace("mark_dead_jobs_as_notified: child_max = %d ndead = %d ndeadproc = %d", js.c_childmax, ndead, ndeadproc);
|
||||
#endif
|
||||
|
||||
/* Mark enough dead jobs as notified that we keep CHILD_MAX jobs in
|
||||
the list. This isn't exactly right yet; changes need to be made
|
||||
to stop_pipeline so we don't mark the newer jobs after we've
|
||||
|
||||
@@ -160,7 +160,9 @@ extern procenv_t wait_intr_buf;
|
||||
extern int wait_signal_received;
|
||||
extern WORD_LIST *subst_assign_varlist;
|
||||
|
||||
struct jobstats js = { -1L, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NO_JOB, NO_JOB };
|
||||
struct jobstats js = { -1L, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NO_JOB, NO_JOB, 0, 0 };
|
||||
|
||||
struct bgpids bgpids = { 0, 0, 0 };
|
||||
|
||||
/* The array of known jobs. */
|
||||
JOB **jobs = (JOB **)NULL;
|
||||
@@ -234,12 +236,14 @@ static sighandler sigstop_sighandler __P((int));
|
||||
static int waitchld __P((pid_t, int));
|
||||
|
||||
static PROCESS *find_pipeline __P((pid_t, int, int *));
|
||||
static PROCESS *find_process __P((pid_t, int, int *));
|
||||
|
||||
static char *current_working_directory __P((void));
|
||||
static char *job_working_directory __P((void));
|
||||
static char *j_strsignal __P((int));
|
||||
static char *printable_job_status __P((int, PROCESS *, int));
|
||||
|
||||
static PROCESS *find_last_proc __P((int, int));
|
||||
static pid_t find_last_pid __P((int, int));
|
||||
|
||||
static int set_new_line_discipline __P((int));
|
||||
@@ -247,7 +251,7 @@ static int map_over_jobs __P((sh_job_map_func_t *, int, int));
|
||||
static int job_last_stopped __P((int));
|
||||
static int job_last_running __P((int));
|
||||
static int most_recent_job_in_state __P((int, JOB_STATE));
|
||||
static int find_job __P((pid_t, int));
|
||||
static int find_job __P((pid_t, int, PROCESS **));
|
||||
static int print_job __P((JOB *, int, int, int));
|
||||
static int process_exit_status __P((WAIT));
|
||||
static int process_exit_signal __P((WAIT));
|
||||
@@ -279,6 +283,13 @@ static void pipe_read __P((int *));
|
||||
static void pipe_close __P((int *));
|
||||
#endif
|
||||
|
||||
static struct pidstat *bgp_alloc __P((pid_t, int));
|
||||
static struct pidstat *bgp_add __P((pid_t, int));
|
||||
static int bgp_delete __P((pid_t));
|
||||
static void bgp_clear __P((void));
|
||||
static int bgp_search __P((pid_t));
|
||||
static void bgp_prune __P((void));
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
static int *pstatuses; /* list of pipeline statuses */
|
||||
static int statsize;
|
||||
@@ -535,7 +546,7 @@ stop_pipeline (async, deferred)
|
||||
if (the_pipeline)
|
||||
{
|
||||
register PROCESS *p;
|
||||
int any_alive, any_stopped, n;
|
||||
int any_running, any_stopped, n;
|
||||
|
||||
newjob = (JOB *)xmalloc (sizeof (JOB));
|
||||
|
||||
@@ -559,16 +570,16 @@ stop_pipeline (async, deferred)
|
||||
|
||||
/* Set the state of this pipeline. */
|
||||
p = newjob->pipe;
|
||||
any_alive = any_stopped = 0;
|
||||
any_running = any_stopped = 0;
|
||||
do
|
||||
{
|
||||
any_alive |= p->running;
|
||||
any_stopped |= WIFSTOPPED (p->status);
|
||||
any_running |= PRUNNING (p);
|
||||
any_stopped |= PSTOPPED (p);
|
||||
p = p->next;
|
||||
}
|
||||
while (p != newjob->pipe);
|
||||
|
||||
newjob->state = any_alive ? JRUNNING : (any_stopped ? JSTOPPED : JDEAD);
|
||||
newjob->state = any_running ? JRUNNING : (any_stopped ? JSTOPPED : JDEAD);
|
||||
newjob->wd = job_working_directory ();
|
||||
newjob->deferred = deferred;
|
||||
|
||||
@@ -581,7 +592,6 @@ stop_pipeline (async, deferred)
|
||||
if (newjob->state == JDEAD)
|
||||
{
|
||||
js.c_reaped += n; /* wouldn't have been done since this was not part of a job */
|
||||
itrace("stop_pipeline: job %d: js.c_reaped (%d) just added (%d)", i, js.c_reaped, n);
|
||||
js.j_ndead++;
|
||||
}
|
||||
js.c_injobs += n;
|
||||
@@ -592,10 +602,17 @@ itrace("stop_pipeline: job %d: js.c_reaped (%d) just added (%d)", i, js.c_reaped
|
||||
else
|
||||
newjob = (JOB *)NULL;
|
||||
|
||||
if (newjob)
|
||||
js.j_lastmade = newjob;
|
||||
|
||||
if (async)
|
||||
{
|
||||
if (newjob)
|
||||
newjob->flags &= ~J_FOREGROUND;
|
||||
{
|
||||
newjob->flags &= ~J_FOREGROUND;
|
||||
newjob->flags |= J_ASYNC;
|
||||
js.j_lastasync = newjob;
|
||||
}
|
||||
reset_current ();
|
||||
}
|
||||
else
|
||||
@@ -622,9 +639,133 @@ itrace("stop_pipeline: job %d: js.c_reaped (%d) just added (%d)", i, js.c_reaped
|
||||
return (js.j_current);
|
||||
}
|
||||
|
||||
/* Functions to manage the list of exited background pids whose status has
|
||||
been saved. */
|
||||
|
||||
static struct pidstat *
|
||||
bgp_alloc (pid, status)
|
||||
pid_t pid;
|
||||
int status;
|
||||
{
|
||||
struct pidstat *ps;
|
||||
|
||||
ps = (struct pidstat *)xmalloc (sizeof (struct pidstat));
|
||||
ps->pid = pid;
|
||||
ps->status = status;
|
||||
ps->next = (struct pidstat *)0;
|
||||
return ps;
|
||||
}
|
||||
|
||||
static struct pidstat *
|
||||
bgp_add (pid, status)
|
||||
pid_t pid;
|
||||
int status;
|
||||
{
|
||||
struct pidstat *ps;
|
||||
|
||||
ps = bgp_alloc (pid, status);
|
||||
|
||||
if (bgpids.list == 0)
|
||||
{
|
||||
bgpids.list = bgpids.end = ps;
|
||||
bgpids.npid = 0; /* just to make sure */
|
||||
}
|
||||
else
|
||||
{
|
||||
bgpids.end->next = ps;
|
||||
bgpids.end = ps;
|
||||
}
|
||||
bgpids.npid++;
|
||||
|
||||
if (bgpids.npid > js.c_childmax)
|
||||
bgp_prune ();
|
||||
|
||||
return ps;
|
||||
}
|
||||
|
||||
static int
|
||||
bgp_delete (pid)
|
||||
pid_t pid;
|
||||
{
|
||||
struct pidstat *prev, *p;
|
||||
|
||||
for (prev = p = bgpids.list; p; prev = p, p = p->next)
|
||||
if (p->pid == pid)
|
||||
{
|
||||
prev->next = p->next; /* remove from list */
|
||||
break;
|
||||
}
|
||||
|
||||
if (p == 0)
|
||||
return 0; /* not found */
|
||||
|
||||
itrace("bgp_delete: deleting %d", pid);
|
||||
|
||||
/* Housekeeping in the border cases. */
|
||||
if (p == bgpids.list)
|
||||
bgpids.list = bgpids.list->next;
|
||||
else if (p == bgpids.end)
|
||||
bgpids.end = prev;
|
||||
|
||||
bgpids.npid--;
|
||||
if (bgpids.npid == 0)
|
||||
bgpids.list = bgpids.end = 0;
|
||||
else if (bgpids.npid == 1)
|
||||
bgpids.end = bgpids.list; /* just to make sure */
|
||||
|
||||
free (p);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Clear out the list of saved statuses */
|
||||
static void
|
||||
bgp_clear ()
|
||||
{
|
||||
struct pidstat *ps, *p;
|
||||
|
||||
for (ps = bgpids.list; ps; )
|
||||
{
|
||||
p = ps;
|
||||
ps = ps->next;
|
||||
free (p);
|
||||
}
|
||||
bgpids.list = bgpids.end = 0;
|
||||
bgpids.npid = 0;
|
||||
}
|
||||
|
||||
/* Search for PID in the list of saved background pids; return its status if
|
||||
found. If not found, return -1. */
|
||||
static int
|
||||
bgp_search (pid)
|
||||
pid_t pid;
|
||||
{
|
||||
struct pidstat *ps;
|
||||
|
||||
for (ps = bgpids.list ; ps; ps = ps->next)
|
||||
if (ps->pid == pid)
|
||||
return ps->status;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
bgp_prune ()
|
||||
{
|
||||
struct pidstat *ps, *p;
|
||||
|
||||
while (bgpids.npid > js.c_childmax)
|
||||
{
|
||||
ps = bgpids.list;
|
||||
itrace("bgp_prune: deleting %d -> %d", ps->pid, bgpids.npid - 1);
|
||||
bgpids.list = bgpids.list->next;
|
||||
free (ps);
|
||||
bgpids.npid--;
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset the values of js.j_lastj and js.j_firstj after one or both have
|
||||
been deleted. The caller should check whether js.j_njobs is 0 before
|
||||
calling this. */
|
||||
calling this. This wraps around, but the rest of the code does not. At
|
||||
this point, it should not matter. */
|
||||
static void
|
||||
reset_job_indices ()
|
||||
{
|
||||
@@ -760,20 +901,30 @@ delete_job (job_index, warn_stopped)
|
||||
int job_index, warn_stopped;
|
||||
{
|
||||
register JOB *temp;
|
||||
int ndel;
|
||||
PROCESS *proc;
|
||||
int ndel, status;
|
||||
pid_t pid;
|
||||
|
||||
if (js.j_jobslots == 0 || jobs_list_frozen)
|
||||
return;
|
||||
|
||||
if (warn_stopped && subshell_environment == 0 && STOPPED (job_index))
|
||||
internal_warning (_("deleting stopped job %d with process group %ld"), job_index+1, (long)jobs[job_index]->pgrp);
|
||||
|
||||
temp = jobs[job_index];
|
||||
if (job_index == js.j_current || job_index == js.j_previous)
|
||||
reset_current ();
|
||||
|
||||
proc = find_last_proc (job_index, 0);
|
||||
/* Could do this just for J_ASYNC jobs, but we save all. */
|
||||
bgp_add (proc->pid, process_exit_status (proc->status));
|
||||
|
||||
jobs[job_index] = (JOB *)NULL;
|
||||
|
||||
if (temp == js.j_lastmade)
|
||||
js.j_lastmade = 0;
|
||||
else if (temp == js.j_lastasync)
|
||||
js.j_lastasync = 0;
|
||||
|
||||
free (temp->wd);
|
||||
ndel = discard_pipeline (temp->pipe);
|
||||
|
||||
@@ -845,6 +996,21 @@ add_process (name, pid)
|
||||
{
|
||||
PROCESS *t, *p;
|
||||
|
||||
#if defined (RECYCLES_PIDS)
|
||||
int j;
|
||||
p = find_process (pid, 0, &j);
|
||||
if (p)
|
||||
{
|
||||
# ifdef DEBUG
|
||||
if (j == NO_JOB)
|
||||
internal_warning ("add_process: process %5ld (%s) in the_pipeline", (long)p->pid, p->command);
|
||||
# endif
|
||||
if (PALIVE (p))
|
||||
internal_warning ("add_process: pid %5ld (%s) marked as still alive", (long)p->pid, p->command);
|
||||
p->running = PS_RECYCLED; /* mark as recycled */
|
||||
}
|
||||
#endif
|
||||
|
||||
t = (PROCESS *)xmalloc (sizeof (PROCESS));
|
||||
t->next = the_pipeline;
|
||||
t->pid = pid;
|
||||
@@ -994,15 +1160,16 @@ kill_current_pipeline ()
|
||||
}
|
||||
|
||||
/* Return the pipeline that PID belongs to. Note that the pipeline
|
||||
doesn't have to belong to a job. Must be called with SIGCHLD blocked. */
|
||||
doesn't have to belong to a job. Must be called with SIGCHLD blocked.
|
||||
If JOBP is non-null, return the index of the job containing PID. */
|
||||
static PROCESS *
|
||||
find_pipeline (pid, running_only, jobp)
|
||||
find_pipeline (pid, alive_only, jobp)
|
||||
pid_t pid;
|
||||
int running_only;
|
||||
int alive_only;
|
||||
int *jobp; /* index into jobs list or NO_JOB */
|
||||
{
|
||||
int job;
|
||||
register PROCESS *p;
|
||||
PROCESS *p;
|
||||
|
||||
/* See if this process is in the pipeline that we are building. */
|
||||
if (jobp)
|
||||
@@ -1012,33 +1179,48 @@ find_pipeline (pid, running_only, jobp)
|
||||
p = the_pipeline;
|
||||
do
|
||||
{
|
||||
/* Return it if we found it. */
|
||||
if (p->pid == pid)
|
||||
{
|
||||
if ((running_only && PALIVE(p)) || (running_only == 0))
|
||||
return (p);
|
||||
}
|
||||
/* Return it if we found it. Don't ever return a recycled pid. */
|
||||
if (p->pid == pid && ((alive_only == 0 && PRECYCLED(p) == 0) || PALIVE(p)))
|
||||
return (p);
|
||||
|
||||
p = p->next;
|
||||
}
|
||||
while (p != the_pipeline);
|
||||
}
|
||||
|
||||
job = find_job (pid, running_only);
|
||||
job = find_job (pid, alive_only, &p);
|
||||
if (jobp)
|
||||
*jobp = job;
|
||||
return (job == NO_JOB) ? (PROCESS *)NULL : jobs[job]->pipe;
|
||||
}
|
||||
|
||||
/* Return the PROCESS * describing PID. If JOBP is non-null return the index
|
||||
into the jobs array of the job containing PID. Must be called with
|
||||
SIGCHLD blocked. */
|
||||
static PROCESS *
|
||||
find_process (pid, alive_only, jobp)
|
||||
pid_t pid;
|
||||
int alive_only;
|
||||
int *jobp; /* index into jobs list or NO_JOB */
|
||||
{
|
||||
PROCESS *p;
|
||||
|
||||
p = find_pipeline (pid, alive_only, jobp);
|
||||
while (p && p->pid != pid)
|
||||
p = p->next;
|
||||
return p;
|
||||
}
|
||||
|
||||
/* Return the job index that PID belongs to, or NO_JOB if it doesn't
|
||||
belong to any job. Must be called with SIGCHLD blocked. */
|
||||
static int
|
||||
find_job (pid, running_only)
|
||||
find_job (pid, alive_only, procp)
|
||||
pid_t pid;
|
||||
int running_only;
|
||||
int alive_only;
|
||||
PROCESS **procp;
|
||||
{
|
||||
register int i;
|
||||
register PROCESS *p;
|
||||
PROCESS *p;
|
||||
|
||||
/* XXX could use js.j_firstj here */
|
||||
for (i = 0; i < js.j_jobslots; i++)
|
||||
@@ -1051,10 +1233,11 @@ if (i < js.j_firstj && jobs[i])
|
||||
|
||||
do
|
||||
{
|
||||
if (p->pid == pid)
|
||||
if (p->pid == pid && ((alive_only == 0 && PRECYCLED(p) == 0) || PALIVE(p)))
|
||||
{
|
||||
if ((running_only && PALIVE(p)) || (running_only == 0))
|
||||
return (i);
|
||||
if (procp)
|
||||
*procp = p;
|
||||
return (i);
|
||||
}
|
||||
|
||||
p = p->next;
|
||||
@@ -1079,7 +1262,7 @@ get_job_by_pid (pid, block)
|
||||
if (block)
|
||||
BLOCK_CHILD (set, oset);
|
||||
|
||||
job = find_job (pid, 0);
|
||||
job = find_job (pid, 0, NULL);
|
||||
|
||||
if (block)
|
||||
UNBLOCK_CHILD (oset);
|
||||
@@ -1097,7 +1280,7 @@ describe_pid (pid)
|
||||
|
||||
BLOCK_CHILD (set, oset);
|
||||
|
||||
job = find_job (pid, 0);
|
||||
job = find_job (pid, 0, NULL);
|
||||
|
||||
if (job != NO_JOB)
|
||||
fprintf (stderr, "[%d] %ld\n", job + 1, (long)pid);
|
||||
@@ -1499,7 +1682,12 @@ make_child (command, async_p)
|
||||
#endif /* PGRP_PIPE */
|
||||
|
||||
if (async_p)
|
||||
last_asynchronous_pid = getpid ();
|
||||
last_asynchronous_pid = mypid;
|
||||
#if defined (RECYCLES_PIDS)
|
||||
else if (last_asynchronous_pid == mypid)
|
||||
/* Avoid pid aliasing. 1 seems like a safe, unusual pid value. */
|
||||
last_asynchronous_pid = 1;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1533,6 +1721,18 @@ make_child (command, async_p)
|
||||
|
||||
if (async_p)
|
||||
last_asynchronous_pid = pid;
|
||||
#if defined (RECYCLES_PIDS)
|
||||
else if (last_asynchronous_pid == pid)
|
||||
/* Avoid pid aliasing. 1 seems like a safe, unusual pid value. */
|
||||
last_asynchronous_pid = 1;
|
||||
#endif
|
||||
|
||||
#if !defined (RECYCLES_PIDS)
|
||||
/* Only check for saved status if we've saved more than CHILD_MAX
|
||||
statuses, unless the system recycles pids. */
|
||||
if ((js.c_reaped + bgpids.npid) >= js.c_childmax)
|
||||
#endif
|
||||
bgp_delete (pid); /* new process, discard any saved status */
|
||||
|
||||
last_made_pid = pid;
|
||||
|
||||
@@ -1696,11 +1896,11 @@ set_tty_state ()
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Given an index into the jobs array JOB, return the pid of the last
|
||||
/* Given an index into the jobs array JOB, return the PROCESS struct of the last
|
||||
process in that job's pipeline. This is the one whose exit status
|
||||
counts. Must be called with SIGCHLD blocked or queued. */
|
||||
static pid_t
|
||||
find_last_pid (job, block)
|
||||
static PROCESS *
|
||||
find_last_proc (job, block)
|
||||
int job;
|
||||
int block;
|
||||
{
|
||||
@@ -1717,9 +1917,21 @@ find_last_pid (job, block)
|
||||
if (block)
|
||||
UNBLOCK_CHILD (oset);
|
||||
|
||||
return (p->pid);
|
||||
return (p);
|
||||
}
|
||||
|
||||
static pid_t
|
||||
find_last_pid (job, block)
|
||||
int job;
|
||||
int block;
|
||||
{
|
||||
PROCESS *p;
|
||||
|
||||
p = find_last_proc (job, block);
|
||||
/* Possible race condition here. */
|
||||
return p->pid;
|
||||
}
|
||||
|
||||
/* Wait for a particular child of the shell to finish executing.
|
||||
This low-level function prints an error message if PID is not
|
||||
a child of this shell. It returns -1 if it fails, or whatever
|
||||
@@ -1737,6 +1949,13 @@ wait_for_single_pid (pid)
|
||||
child = find_pipeline (pid, 0, (int *)NULL);
|
||||
UNBLOCK_CHILD (oset);
|
||||
|
||||
if (child == 0)
|
||||
{
|
||||
r = bgp_search (pid);
|
||||
if (r >= 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (child == 0)
|
||||
{
|
||||
internal_error (_("wait: pid %ld is not a child of this shell"), (long)pid);
|
||||
@@ -1748,7 +1967,7 @@ wait_for_single_pid (pid)
|
||||
/* POSIX.2: if we just waited for a job, we can remove it from the jobs
|
||||
table. */
|
||||
BLOCK_CHILD (set, oset);
|
||||
job = find_job (pid, 0);
|
||||
job = find_job (pid, 0, NULL);
|
||||
if (job != NO_JOB && jobs[job] && DEADJOB (job))
|
||||
jobs[job]->flags |= J_NOTIFIED;
|
||||
UNBLOCK_CHILD (oset);
|
||||
@@ -1803,6 +2022,7 @@ if (i < js.j_firstj && jobs[i])
|
||||
`wait' is called with no arguments. */
|
||||
mark_dead_jobs_as_notified (1);
|
||||
cleanup_dead_jobs ();
|
||||
bgp_clear ();
|
||||
}
|
||||
|
||||
/* Make OLD_SIGINT_HANDLER the SIGINT signal handler. */
|
||||
@@ -1986,13 +2206,13 @@ wait_for (pid)
|
||||
We check for JDEAD in case the job state has been set by waitchld
|
||||
after receipt of a SIGCHLD. */
|
||||
if (job == NO_JOB)
|
||||
job = find_job (pid, 0);
|
||||
job = find_job (pid, 0, NULL);
|
||||
|
||||
/* waitchld() takes care of setting the state of the job. If the job
|
||||
has already exited before this is called, sigchld_handler will have
|
||||
called waitchld and the state will be set to JDEAD. */
|
||||
|
||||
if (child->running || (job != NO_JOB && RUNNING (job)))
|
||||
if (PRUNNING(child) || (job != NO_JOB && RUNNING (job)))
|
||||
{
|
||||
#if defined (WAITPID_BROKEN) /* SCOv4 */
|
||||
sigset_t suspend_set;
|
||||
@@ -2049,7 +2269,7 @@ wait_for (pid)
|
||||
if (interactive && job_control == 0)
|
||||
QUIT;
|
||||
}
|
||||
while (child->running || (job != NO_JOB && RUNNING (job)));
|
||||
while (PRUNNING (child) || (job != NO_JOB && RUNNING (job)));
|
||||
|
||||
/* The exit state of the command is either the termination state of the
|
||||
child, or the termination state of the job. If a job, the status
|
||||
@@ -2529,8 +2749,11 @@ kill_pid (pid, sig, group)
|
||||
|
||||
do
|
||||
{
|
||||
if (PALIVE (p) == 0)
|
||||
continue; /* avoid pid recycling problems */
|
||||
|
||||
kill (p->pid, sig);
|
||||
if (p->running == PS_DONE && (sig == SIGTERM || sig == SIGHUP))
|
||||
if (PEXITED (p) && (sig == SIGTERM || sig == SIGHUP))
|
||||
kill (p->pid, SIGCONT);
|
||||
p = p->next;
|
||||
}
|
||||
@@ -2637,7 +2860,7 @@ waitchld (wpid, block)
|
||||
children_exited++;
|
||||
|
||||
/* Locate our PROCESS for this pid. */
|
||||
child = find_pipeline (pid, 1, &job); /* want running procs only */
|
||||
child = find_process (pid, 1, &job); /* want living procs only */
|
||||
|
||||
/* It is not an error to have a child terminate that we did
|
||||
not have a record of. This child could have been part of
|
||||
@@ -2646,21 +2869,15 @@ waitchld (wpid, block)
|
||||
if (child == 0)
|
||||
continue;
|
||||
|
||||
while (child->pid != pid)
|
||||
child = child->next;
|
||||
|
||||
/* Remember status, and whether or not the process is running. */
|
||||
child->status = status;
|
||||
child->running = WIFCONTINUED(status) ? PS_RUNNING : PS_DONE;
|
||||
|
||||
if (child->running == PS_DONE)
|
||||
if (PEXITED (child))
|
||||
{
|
||||
js.c_totreaped++;
|
||||
if (job != NO_JOB)
|
||||
{
|
||||
js.c_reaped++;
|
||||
itrace("waitchld: job %d js.c_reaped++ = %d", job, js.c_reaped);
|
||||
}
|
||||
}
|
||||
|
||||
if (job == NO_JOB)
|
||||
@@ -2727,8 +2944,13 @@ set_job_status_and_cleanup (job)
|
||||
job_state = any_stopped = any_tstped = 0;
|
||||
do
|
||||
{
|
||||
job_state |= child->running;
|
||||
if (child->running == PS_DONE && (WIFSTOPPED (child->status)))
|
||||
job_state |= PRUNNING (child);
|
||||
#if 0
|
||||
if (PEXITED (child) && (WIFSTOPPED (child->status)))
|
||||
#else
|
||||
/* Only checking for WIFSTOPPED now, not for PS_DONE */
|
||||
if (PSTOPPED (child))
|
||||
#endif
|
||||
{
|
||||
any_stopped = 1;
|
||||
any_tstped |= interactive && job_control &&
|
||||
@@ -3185,6 +3407,11 @@ initialize_job_control (force)
|
||||
if (interactive)
|
||||
get_tty_state ();
|
||||
|
||||
if (js.c_childmax < 0)
|
||||
js.c_childmax = getmaxchild ();
|
||||
if (js.c_childmax < 0)
|
||||
js.c_childmax = DEFAULT_CHILD_MAX;
|
||||
|
||||
return job_control;
|
||||
}
|
||||
|
||||
@@ -3434,6 +3661,9 @@ if (i < js.j_firstj && jobs[i])
|
||||
}
|
||||
}
|
||||
|
||||
if (running_only == 0)
|
||||
bgp_clear ();
|
||||
|
||||
UNBLOCK_CHILD (oset);
|
||||
}
|
||||
|
||||
@@ -3532,7 +3762,10 @@ mark_dead_jobs_as_notified (force)
|
||||
}
|
||||
|
||||
/* Mark enough dead jobs as notified to keep CHILD_MAX processes left in the
|
||||
array with the corresponding not marked as notified. */
|
||||
array with the corresponding not marked as notified. This is a better
|
||||
way to avoid pid aliasing and reuse problems than keeping the POSIX-
|
||||
mandated CHILD_MAX jobs around. delete_job() takes care of keeping the
|
||||
bgpids list regulated. */
|
||||
|
||||
/* Count the number of dead jobs */
|
||||
/* XXX could use js.j_firstj here */
|
||||
@@ -3547,16 +3780,18 @@ if (i < js.j_firstj && jobs[i])
|
||||
}
|
||||
}
|
||||
|
||||
if (ndeadproc != js.c_reaped)
|
||||
itrace("mark_dead_jobs_as_notified: ndeadproc (%d) != js.c_reaped (%d)", ndeadproc, js.c_reaped);
|
||||
if (ndead != js.j_ndead)
|
||||
itrace("mark_dead_jobs_as_notified: ndead (%d) != js.j_ndead (%d)", ndead, js.j_ndead);
|
||||
#ifdef DEBUG
|
||||
if (ndeadproc != js.c_reaped)
|
||||
itrace("mark_dead_jobs_as_notified: ndeadproc (%d) != js.c_reaped (%d)", ndeadproc, js.c_reaped);
|
||||
if (ndead != js.j_ndead)
|
||||
itrace("mark_dead_jobs_as_notified: ndead (%d) != js.j_ndead (%d)", ndead, js.j_ndead);
|
||||
#endif
|
||||
|
||||
if (js.c_childmax < 0)
|
||||
js.c_childmax = getmaxchild ();
|
||||
if (js.c_childmax < 0)
|
||||
js.c_childmax = DEFAULT_CHILD_MAX;
|
||||
|
||||
itrace("mark_dead_jobs_as_notified: child_max = %d ndead = %d ndeadproc = %d", js.c_childmax, ndead, ndeadproc);
|
||||
/* Don't do anything if the number of dead processes is less than CHILD_MAX
|
||||
and we're not forcing a cleanup. */
|
||||
if (ndeadproc <= js.c_childmax)
|
||||
@@ -3565,6 +3800,10 @@ itrace("mark_dead_jobs_as_notified: child_max = %d ndead = %d ndeadproc = %d", j
|
||||
return;
|
||||
}
|
||||
|
||||
#if 0
|
||||
itrace("mark_dead_jobs_as_notified: child_max = %d ndead = %d ndeadproc = %d", js.c_childmax, ndead, ndeadproc);
|
||||
#endif
|
||||
|
||||
/* Mark enough dead jobs as notified that we keep CHILD_MAX jobs in
|
||||
the list. This isn't exactly right yet; changes need to be made
|
||||
to stop_pipeline so we don't mark the newer jobs after we've
|
||||
@@ -3590,7 +3829,6 @@ if (i < js.j_firstj && jobs[i])
|
||||
if ((ndeadproc -= processes_in_job (i)) <= js.c_childmax)
|
||||
break;
|
||||
jobs[i]->flags |= J_NOTIFIED;
|
||||
itrace("marking job %d as notified", i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* jobs.h -- structures and stuff used by the jobs.c file. */
|
||||
|
||||
/* Copyright (C) 1993-2004 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1993-2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -46,9 +46,10 @@
|
||||
#define PS_DONE 0
|
||||
#define PS_RUNNING 1
|
||||
#define PS_STOPPED 2
|
||||
#define PS_RECYCLED 4
|
||||
|
||||
/* Each child of the shell is remembered in a STRUCT PROCESS. A chain of
|
||||
such structures is a pipeline. The chain is circular. */
|
||||
/* Each child of the shell is remembered in a STRUCT PROCESS. A circular
|
||||
chain of such structures is a pipeline. */
|
||||
typedef struct process {
|
||||
struct process *next; /* Next process in the pipeline. A circular chain. */
|
||||
pid_t pid; /* Process ID. */
|
||||
@@ -57,10 +58,18 @@ typedef struct process {
|
||||
char *command; /* The particular program that is running. */
|
||||
} PROCESS;
|
||||
|
||||
/* PRUNNING really means `not exited' */
|
||||
#define PALIVE(p) ((p)->running || WIFSTOPPED((p)->status))
|
||||
/* PALIVE really means `not exited' */
|
||||
#define PSTOPPED(p) (WIFSTOPPED((p)->status))
|
||||
#define PDEADPROC(p) ((p)->running == PS_DONE)
|
||||
#define PRUNNING(p) ((p)->running == PS_RUNNING)
|
||||
#define PALIVE(p) (PRUNNING(p) || PSTOPPED(p))
|
||||
|
||||
#define PEXITED(p) ((p)->running == PS_DONE)
|
||||
#if defined (RECYCLES_PIDS)
|
||||
# define PRECYCLED(p) ((p)->running == PS_RECYCLED)
|
||||
#else
|
||||
# define PRECYCLED(p) (0)
|
||||
#endif
|
||||
#define PDEADPROC(p) (PEXITED(p) || PRECYCLED(p))
|
||||
|
||||
#define get_job_by_jid(ind) (jobs[(ind)])
|
||||
|
||||
@@ -73,7 +82,7 @@ typedef enum { JRUNNING, JSTOPPED, JDEAD, JMIXED } JOB_STATE;
|
||||
#define RUNNING(j) (jobs[(j)]->state == JRUNNING)
|
||||
#define DEADJOB(j) (jobs[(j)]->state == JDEAD)
|
||||
|
||||
#define INVALID_JOB(j) ((j) < 0 || (j) >= js.j_jobslots || jobs[(j)] == 0)
|
||||
#define INVALID_JOB(j) ((j) < 0 || (j) >= js.j_jobslots || get_job_by_jid(j) == 0)
|
||||
|
||||
/* Values for the FLAGS field in the JOB struct below. */
|
||||
#define J_FOREGROUND 0x01 /* Non-zero if this is running in the foreground. */
|
||||
@@ -81,10 +90,12 @@ typedef enum { JRUNNING, JSTOPPED, JDEAD, JMIXED } JOB_STATE;
|
||||
#define J_JOBCONTROL 0x04 /* Non-zero if this job started under job control. */
|
||||
#define J_NOHUP 0x08 /* Don't send SIGHUP to job if shell gets SIGHUP. */
|
||||
#define J_STATSAVED 0x10 /* A process in this job had had status saved via $! */
|
||||
#define J_ASYNC 0x20 /* Job was started asynchronously */
|
||||
|
||||
#define IS_FOREGROUND(j) ((jobs[j]->flags & J_FOREGROUND) != 0)
|
||||
#define IS_NOTIFIED(j) ((jobs[j]->flags & J_NOTIFIED) != 0)
|
||||
#define IS_JOBCONTROL(j) ((jobs[j]->flags & J_JOBCONTROL) != 0)
|
||||
#define IS_ASYNC(j) ((jobs[j]->flags & J_ASYNC) != 0)
|
||||
|
||||
typedef struct job {
|
||||
char *wd; /* The working directory at time of invocation. */
|
||||
@@ -118,6 +129,21 @@ struct jobstats {
|
||||
/* */
|
||||
int j_current; /* current job */
|
||||
int j_previous; /* previous job */
|
||||
/* */
|
||||
JOB *j_lastmade; /* last job allocated by stop_pipeline */
|
||||
JOB *j_lastasync; /* last async job allocated by stop_pipeline */
|
||||
};
|
||||
|
||||
struct pidstat {
|
||||
struct pidstat *next;
|
||||
pid_t pid;
|
||||
int status;
|
||||
};
|
||||
|
||||
struct bgpids {
|
||||
struct pidstat *list;
|
||||
struct pidstat *end;
|
||||
int npid;
|
||||
};
|
||||
|
||||
#define NO_JOB -1 /* An impossible job array index. */
|
||||
@@ -137,10 +163,9 @@ extern struct jobstats js;
|
||||
|
||||
extern pid_t original_pgrp, shell_pgrp, pipeline_pgrp;
|
||||
extern pid_t last_made_pid, last_asynchronous_pid;
|
||||
extern int current_job, previous_job;
|
||||
extern int asynchronous_notification;
|
||||
|
||||
extern JOB **jobs;
|
||||
extern int job_slots;
|
||||
|
||||
extern void making_children __P((void));
|
||||
extern void stop_making_children __P((void));
|
||||
|
||||
@@ -57,7 +57,7 @@ typedef struct process {
|
||||
char *command; /* The particular program that is running. */
|
||||
} PROCESS;
|
||||
|
||||
/* PRUNNING really means `not exited' */
|
||||
/* PALIVE really means `not exited' */
|
||||
#define PALIVE(p) ((p)->running || WIFSTOPPED((p)->status))
|
||||
#define PSTOPPED(p) (WIFSTOPPED((p)->status))
|
||||
#define PDEADPROC(p) ((p)->running == PS_DONE)
|
||||
@@ -73,7 +73,7 @@ typedef enum { JRUNNING, JSTOPPED, JDEAD, JMIXED } JOB_STATE;
|
||||
#define RUNNING(j) (jobs[(j)]->state == JRUNNING)
|
||||
#define DEADJOB(j) (jobs[(j)]->state == JDEAD)
|
||||
|
||||
#define INVALID_JOB(j) ((j) < 0 || (j) >= js.j_jobslots || jobs[(j)] == 0)
|
||||
#define INVALID_JOB(j) ((j) < 0 || (j) >= js.j_jobslots || get_job_by_jid(j) == 0)
|
||||
|
||||
/* Values for the FLAGS field in the JOB struct below. */
|
||||
#define J_FOREGROUND 0x01 /* Non-zero if this is running in the foreground. */
|
||||
@@ -81,10 +81,12 @@ typedef enum { JRUNNING, JSTOPPED, JDEAD, JMIXED } JOB_STATE;
|
||||
#define J_JOBCONTROL 0x04 /* Non-zero if this job started under job control. */
|
||||
#define J_NOHUP 0x08 /* Don't send SIGHUP to job if shell gets SIGHUP. */
|
||||
#define J_STATSAVED 0x10 /* A process in this job had had status saved via $! */
|
||||
#define J_ASYNC 0x20 /* Job was started asynchronously */
|
||||
|
||||
#define IS_FOREGROUND(j) ((jobs[j]->flags & J_FOREGROUND) != 0)
|
||||
#define IS_NOTIFIED(j) ((jobs[j]->flags & J_NOTIFIED) != 0)
|
||||
#define IS_JOBCONTROL(j) ((jobs[j]->flags & J_JOBCONTROL) != 0)
|
||||
#define IS_ASYNC(j) ((jobs[j]->flags & J_ASYNC) != 0)
|
||||
|
||||
typedef struct job {
|
||||
char *wd; /* The working directory at time of invocation. */
|
||||
@@ -114,9 +116,25 @@ struct jobstats {
|
||||
int j_lastj; /* last (newest) job allocated */
|
||||
int j_firstj; /* first (oldest) job allocated */
|
||||
int j_njobs; /* number of non-NULL jobs in jobs array */
|
||||
int j_ndead; /* number of JDEAD jobs in jobs array */
|
||||
/* */
|
||||
int j_current; /* current job */
|
||||
int j_previous; /* previous job */
|
||||
/* */
|
||||
JOB *j_lastmade; /* last job allocated by stop_pipeline */
|
||||
JOB *j_lastasync; /* last async job allocated by stop_pipeline */
|
||||
};
|
||||
|
||||
struct pidstat {
|
||||
struct pidstat *next;
|
||||
pid_t pid;
|
||||
int status;
|
||||
};
|
||||
|
||||
struct bgpids {
|
||||
struct pidstat *list;
|
||||
struct pidstat *end;
|
||||
int npid;
|
||||
};
|
||||
|
||||
#define NO_JOB -1 /* An impossible job array index. */
|
||||
@@ -136,10 +154,9 @@ extern struct jobstats js;
|
||||
|
||||
extern pid_t original_pgrp, shell_pgrp, pipeline_pgrp;
|
||||
extern pid_t last_made_pid, last_asynchronous_pid;
|
||||
extern int current_job, previous_job;
|
||||
extern int asynchronous_notification;
|
||||
|
||||
extern JOB **jobs;
|
||||
extern int job_slots;
|
||||
|
||||
extern void making_children __P((void));
|
||||
extern void stop_making_children __P((void));
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# simple makefile to create texindex
|
||||
#
|
||||
# Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1996-2005 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
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
# simple makefile to create texindex
|
||||
#
|
||||
# Copyright (C) 1996 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
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program 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 this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
|
||||
topdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = .:@srcdir@
|
||||
BUILD_DIR = @BUILD_DIR@
|
||||
|
||||
CC = @CC@
|
||||
RM = rm
|
||||
|
||||
SHELL = @MAKE_SHELL@
|
||||
|
||||
DEFS = @DEFS@
|
||||
CFLAGS = @CFLAGS@ @LOCAL_CFLAGS@
|
||||
LDFLAGS = @LDFLAGS@ @LOCAL_LDFLAGS@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
|
||||
INCLUDES = -I. -I../.. -I$(topdir)
|
||||
|
||||
CCFLAGS = $(CFLAGS) $(DEFS) $(CPPFLAGS) ${INCLUDES}
|
||||
|
||||
.c.o:
|
||||
$(RM) -f $@
|
||||
$(CC) $(CCFLAGS) -c $<
|
||||
|
||||
OBJECTS = texindex.o getopt.o getopt1.o
|
||||
SOURCES = texindex.c getopt.c getopt1.c
|
||||
|
||||
all: texindex
|
||||
|
||||
texindex: $(OBJECTS)
|
||||
$(CC) $(LDFLAGS) -o $@ $(OBJECTS) $(LIBS)
|
||||
|
||||
clean:
|
||||
$(RM) $(OBJECTS) texindex
|
||||
|
||||
distclean mostlyclean realclean maintainer-clean: clean
|
||||
$(RM) Makefile
|
||||
@@ -4,7 +4,7 @@
|
||||
# #
|
||||
####################################################################
|
||||
#
|
||||
# Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1996-2005 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
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
## -*- text -*- ####################################################
|
||||
# #
|
||||
# Makefile for the GNU Glob Library. #
|
||||
# #
|
||||
####################################################################
|
||||
#
|
||||
# Copyright (C) 1996 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
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program 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 this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = .:@srcdir@
|
||||
topdir = @top_srcdir@
|
||||
BUILD_DIR = @BUILD_DIR@
|
||||
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
|
||||
CC = @CC@
|
||||
RANLIB = @RANLIB@
|
||||
AR = @AR@
|
||||
ARFLAGS = @ARFLAGS@
|
||||
RM = rm
|
||||
CP = cp
|
||||
MV = mv
|
||||
|
||||
SHELL = @MAKE_SHELL@
|
||||
|
||||
PROFILE_FLAGS = @PROFILE_FLAGS@
|
||||
|
||||
CFLAGS = @CFLAGS@
|
||||
LOCAL_CFLAGS = @LOCAL_CFLAGS@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
LDFLAGS = @LDFLAGS@ @LOCAL_LDFLAGS@
|
||||
|
||||
DEFS = @DEFS@
|
||||
LOCAL_DEFS = @LOCAL_DEFS@
|
||||
|
||||
BASHINCDIR = ${topdir}/include
|
||||
|
||||
INCLUDES = -I. -I../.. -I$(topdir) -I$(BASHINCDIR) -I$(topdir)/lib
|
||||
|
||||
CCFLAGS = $(PROFILE_FLAGS) $(DEFS) $(LOCAL_DEFS) $(CPPFLAGS) ${INCLUDES} \
|
||||
$(LOCAL_CFLAGS) $(CFLAGS)
|
||||
|
||||
# Here is a rule for making .o files from .c files that doesn't force
|
||||
# the type of the machine (like -sun3) into the flags.
|
||||
.c.o:
|
||||
$(CC) -c $(CCFLAGS) $<
|
||||
|
||||
# The name of the library target.
|
||||
LIBRARY_NAME = libglob.a
|
||||
|
||||
# The C code source files for this library.
|
||||
CSOURCES = $(srcdir)/glob.c $(srcdir)/strmatch.c $(srcdir)/smatch.c \
|
||||
$(srcdir)/xmbsrtowcs.c
|
||||
|
||||
# The header files for this library.
|
||||
HSOURCES = $(srcdir)/strmatch.h
|
||||
|
||||
OBJECTS = glob.o strmatch.o smatch.o xmbsrtowcs.o
|
||||
|
||||
# The texinfo files which document this library.
|
||||
DOCSOURCE = doc/glob.texi
|
||||
DOCOBJECT = doc/glob.dvi
|
||||
DOCSUPPORT = doc/Makefile
|
||||
DOCUMENTATION = $(DOCSOURCE) $(DOCOBJECT) $(DOCSUPPORT)
|
||||
|
||||
SUPPORT = Makefile ChangeLog $(DOCSUPPORT)
|
||||
|
||||
SOURCES = $(CSOURCES) $(HSOURCES) $(DOCSOURCE)
|
||||
|
||||
THINGS_TO_TAR = $(SOURCES) $(SUPPORT)
|
||||
|
||||
######################################################################
|
||||
|
||||
all: $(LIBRARY_NAME)
|
||||
|
||||
$(LIBRARY_NAME): $(OBJECTS)
|
||||
$(RM) -f $@
|
||||
$(AR) $(ARFLAGS) $@ $(OBJECTS)
|
||||
-test -n "$(RANLIB)" && $(RANLIB) $@
|
||||
|
||||
what-tar:
|
||||
@for file in $(THINGS_TO_TAR); do \
|
||||
echo $(selfdir)$$file; \
|
||||
done
|
||||
|
||||
documentation: force
|
||||
-(cd doc; $(MAKE) $(MFLAGS))
|
||||
force:
|
||||
|
||||
# The rule for 'includes' is written funny so that the if statement
|
||||
# always returns TRUE unless there really was an error installing the
|
||||
# include files.
|
||||
install:
|
||||
|
||||
clean:
|
||||
rm -f $(OBJECTS) $(LIBRARY_NAME)
|
||||
-(cd doc && $(MAKE) $(MFLAGS) $@ )
|
||||
|
||||
realclean distclean maintainer-clean: clean
|
||||
-( cd doc && $(MAKE) $(MFLAGS) $@ )
|
||||
$(RM) -f Makefile
|
||||
|
||||
mostlyclean: clean
|
||||
-( cd doc && $(MAKE) $(MFLAGS) $@ )
|
||||
|
||||
######################################################################
|
||||
# #
|
||||
# Dependencies for the object files which make up this library. #
|
||||
# #
|
||||
######################################################################
|
||||
|
||||
smatch.o: strmatch.h
|
||||
smatch.o: $(BUILD_DIR)/config.h
|
||||
smatch.o: $(BASHINCDIR)/chartypes.h
|
||||
smatch.o: $(BASHINCDIR)/ansi_stdlib.h $(topdir)/bashansi.h
|
||||
smatch.o: $(BASHINCDIR)/shmbutil.h
|
||||
smatch.o: $(topdir)/xmalloc.h
|
||||
|
||||
strmatch.o: strmatch.h
|
||||
strmatch.o: $(BUILD_DIR)/config.h
|
||||
strmatch.o: $(BASHINCDIR)/stdc.h
|
||||
|
||||
glob.o: $(BUILD_DIR)/config.h
|
||||
glob.o: $(topdir)/bashtypes.h $(BASHINCDIR)/ansi_stdlib.h $(topdir)/bashansi.h
|
||||
glob.o: $(BASHINCDIR)/posixstat.h $(BASHINCDIR)/memalloc.h
|
||||
glob.o: strmatch.h glob.h
|
||||
glob.o: $(BASHINCDIR)/shmbutil.h
|
||||
glob.o: $(topdir)/xmalloc.h
|
||||
|
||||
xmbsrtowcs.o: ${BUILD_DIR}/config.h
|
||||
xmbsrtowcs.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
|
||||
xmbsrtowcs.o: ${BASHINCDIR}/shmbutil.h
|
||||
|
||||
# Rules for deficient makes, like SunOS and Solaris
|
||||
glob.o: glob.c
|
||||
strmatch.o: strmatch.c
|
||||
smatch.o: smatch.c
|
||||
xmbsrtowcs.o: xmbsrtowcs.c
|
||||
|
||||
# dependencies for C files that include other C files
|
||||
glob.o: glob_loop.c
|
||||
smatch.o: sm_loop.c
|
||||
@@ -1,7 +1,7 @@
|
||||
# Skeleton Makefile for the GNU malloc code
|
||||
#
|
||||
#
|
||||
# Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1996-2005 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
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
# Skeleton Makefile for the GNU malloc code
|
||||
#
|
||||
#
|
||||
# Copyright (C) 1996 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
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program 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 this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = .:@srcdir@
|
||||
topdir = @top_srcdir@
|
||||
BUILD_DIR = @BUILD_DIR@
|
||||
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
|
||||
CC = @CC@
|
||||
RANLIB = @RANLIB@
|
||||
AR = @AR@
|
||||
ARFLAGS = @ARFLAGS@
|
||||
RM = rm -f
|
||||
CP = cp
|
||||
MV = mv
|
||||
|
||||
SHELL = @MAKE_SHELL@
|
||||
|
||||
PROFILE_FLAGS = @PROFILE_FLAGS@
|
||||
|
||||
CFLAGS = @CFLAGS@
|
||||
LOCAL_CFLAGS = @LOCAL_CFLAGS@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
DEFS = @DEFS@
|
||||
LOCAL_DEFS = @LOCAL_DEFS@
|
||||
|
||||
LIBBUILD = ${BUILD_DIR}/lib
|
||||
|
||||
BASHINCDIR = ${topdir}/include
|
||||
|
||||
INTL_LIBSRC = ${topdir}/lib/intl
|
||||
INTL_BUILDDIR = ${LIBBUILD}/intl
|
||||
INTL_INC = @INTL_INC@
|
||||
LIBINTL_H = @LIBINTL_H@
|
||||
|
||||
INCLUDES = -I. -I../.. -I$(topdir) -I$(BASHINCDIR) -I$(topdir)/lib $(INTL_INC)
|
||||
|
||||
CCFLAGS = ${PROFILE_FLAGS} ${INCLUDES} $(DEFS) $(LOCAL_DEFS) $(LOCAL_CFLAGS) \
|
||||
$(CFLAGS) $(MALLOC_CFLAGS) $(CPPFLAGS)
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CCFLAGS) -c $<
|
||||
|
||||
.s.o:
|
||||
$(CC) $(CCFLAGS) -c $<
|
||||
|
||||
MALLOC_SOURCE = malloc.c
|
||||
STUB_SOURCE = stub.c
|
||||
|
||||
ALLOCA_SOURCE = alloca.c
|
||||
ALLOCA_OBJECT = alloca.o
|
||||
|
||||
MALLOC_SRC = @MALLOC_SRC@
|
||||
MALLOC = @MALLOC@
|
||||
ALLOCA = @ALLOCA@
|
||||
|
||||
MALLOC_OBJS = malloc.o $(ALLOCA) trace.o stats.o table.o watch.o
|
||||
STUB_OBJS = $(ALLOCA) stub.o
|
||||
|
||||
.PHONY: malloc stubmalloc
|
||||
|
||||
all: malloc
|
||||
|
||||
malloc: ${MALLOC_OBJS}
|
||||
${RM} libmalloc.a
|
||||
${AR} ${ARFLAGS} libmalloc.a ${MALLOC_OBJS}
|
||||
-test -n "$(RANLIB)" && $(RANLIB) libmalloc.a
|
||||
|
||||
stubmalloc: ${STUB_OBJS}
|
||||
${RM} libmalloc.a
|
||||
${AR} ${ARFLAGS} libmalloc.a ${STUB_OBJS}
|
||||
-test -n "$(RANLIB)" && $(RANLIB) libmalloc.a
|
||||
|
||||
alloca: ${ALLOCA}
|
||||
${RM} libmalloc.a
|
||||
${AR} ${ARFLAGS} libmalloc.a ${ALLOCA}
|
||||
-test -n "$(RANLIB)" && $(RANLIB) libmalloc.a
|
||||
|
||||
alloca.o: $(srcdir)/$(ALLOCA_SOURCE)
|
||||
$(CC) $(CCFLAGS) -c $(srcdir)/$(ALLOCA_SOURCE)
|
||||
@- if test "$(ALLOCA_OBJECT)" != alloca.o ; then \
|
||||
mv $(ALLOCA_OBJECT) alloca.o >/dev/null 2>&1 ; \
|
||||
fi
|
||||
|
||||
mostlyclean clean:
|
||||
$(RM) *.o libmalloc.a
|
||||
|
||||
distclean realclean maintainer-clean: clean
|
||||
$(RM) Makefile
|
||||
|
||||
alloca.o: $(BUILD_DIR)/config.h
|
||||
malloc.o: $(BUILD_DIR)/config.h $(topdir)/bashtypes.h getpagesize.h
|
||||
xmalloc.o: $(BUILD_DIR)/config.h $(BASHINCDIR)/ansi_stdlib.h
|
||||
trace.o: ${BUILD_DIR}/config.h
|
||||
table.o: ${BUILD_DIR}/config.h
|
||||
|
||||
malloc.o: ${srcdir}/imalloc.h ${srcdir}/mstats.h
|
||||
malloc.o: ${srcdir}/table.h ${srcdir}/watch.h
|
||||
stats.o: ${srcdir}/imalloc.h ${srcdir}/mstats.h
|
||||
trace.o: ${srcdir}/imalloc.h
|
||||
table.o: ${srcdir}/imalloc.h ${srcdir}/table.h
|
||||
watch.o: ${srcdir}/imalloc.h ${srcdir}/watch.h
|
||||
|
||||
malloc.o: ${topdir}/bashintl.h ${LIBINTL_H} ${BASHINCDIR}/gettext.h
|
||||
stats.o: ${topdir}/bashintl.h ${LIBINTL_H} ${BASHINCDIR}/gettext.h
|
||||
trace.o: ${topdir}/bashintl.h ${LIBINTL_H} ${BASHINCDIR}/gettext.h
|
||||
table.o: ${topdir}/bashintl.h ${LIBINTL_H} ${BASHINCDIR}/gettext.h
|
||||
watch.o: ${topdir}/bashintl.h ${LIBINTL_H} ${BASHINCDIR}/gettext.h
|
||||
|
||||
# Rules for deficient makes, like SunOS and Solaris
|
||||
stub.o: stub.c
|
||||
malloc.o: malloc.c
|
||||
table.o: table.c
|
||||
trace.o: trace.c
|
||||
stats.o: stats.c
|
||||
watch.o: watch.c
|
||||
@@ -4,7 +4,7 @@
|
||||
# #
|
||||
#############################################################################
|
||||
|
||||
# Copyright (C) 1994 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1994-2005 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
|
||||
|
||||
@@ -0,0 +1,366 @@
|
||||
## -*- text -*- #############################################################
|
||||
# #
|
||||
# Makefile for the Bash versions of the GNU Readline and History Libraries. #
|
||||
# #
|
||||
#############################################################################
|
||||
|
||||
# Copyright (C) 1994 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
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program 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 this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
|
||||
PACKAGE = @PACKAGE_NAME@
|
||||
VERSION = @PACKAGE_VERSION@
|
||||
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = .:@srcdir@
|
||||
topdir = @top_srcdir@
|
||||
BUILD_DIR = @BUILD_DIR@
|
||||
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
|
||||
CC = @CC@
|
||||
RANLIB = @RANLIB@
|
||||
AR = @AR@
|
||||
ARFLAGS = @ARFLAGS@
|
||||
RM = rm -f
|
||||
CP = cp
|
||||
MV = mv
|
||||
|
||||
SHELL = @MAKE_SHELL@
|
||||
|
||||
# Programs to make tags files.
|
||||
ETAGS = etags -tw
|
||||
CTAGS = ctags -tw
|
||||
|
||||
CFLAGS = @CFLAGS@
|
||||
LOCAL_CFLAGS = @LOCAL_CFLAGS@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
DEFS = @DEFS@
|
||||
LOCAL_DEFS = @LOCAL_DEFS@
|
||||
|
||||
INCLUDES = -I. -I$(BUILD_DIR) -I$(topdir) -I$(topdir)/lib
|
||||
|
||||
CCFLAGS = $(DEFS) $(LOCAL_DEFS) $(APP_CFLAGS) $(CPPFLAGS) ${INCLUDES} $(LOCAL_CFLAGS) $(CFLAGS)
|
||||
|
||||
.c.o:
|
||||
${RM} $@
|
||||
$(CC) -c $(CCFLAGS) $<
|
||||
|
||||
# The name of the main library target.
|
||||
LIBRARY_NAME = libreadline.a
|
||||
|
||||
# The C code source files for this library.
|
||||
CSOURCES = $(srcdir)/readline.c $(srcdir)/funmap.c $(srcdir)/keymaps.c \
|
||||
$(srcdir)/vi_mode.c $(srcdir)/parens.c $(srcdir)/rltty.c \
|
||||
$(srcdir)/complete.c $(srcdir)/bind.c $(srcdir)/isearch.c \
|
||||
$(srcdir)/display.c $(srcdir)/signals.c $(srcdir)/emacs_keymap.c \
|
||||
$(srcdir)/vi_keymap.c $(srcdir)/util.c $(srcdir)/kill.c \
|
||||
$(srcdir)/undo.c $(srcdir)/macro.c $(srcdir)/input.c \
|
||||
$(srcdir)/callback.c $(srcdir)/terminal.c $(srcdir)/xmalloc.c \
|
||||
$(srcdir)/history.c $(srcdir)/histsearch.c $(srcdir)/histexpand.c \
|
||||
$(srcdir)/histfile.c $(srcdir)/nls.c $(srcdir)/search.c \
|
||||
$(srcdir)/shell.c $(srcdir)/tilde.c $(srcdir)/savestring.c \
|
||||
$(srcdir)/text.c $(srcdir)/misc.c $(srcdir)/compat.c \
|
||||
$(srcdir)/mbutil.c
|
||||
|
||||
# The header files for this library.
|
||||
HSOURCES = readline.h rldefs.h chardefs.h keymaps.h history.h histlib.h \
|
||||
posixstat.h posixdir.h posixjmp.h tilde.h rlconf.h rltty.h \
|
||||
ansi_stdlib.h rlstdc.h tcap.h xmalloc.h rlprivate.h rlshell.h \
|
||||
rltypedefs.h rlmbutil.h
|
||||
|
||||
HISTOBJ = history.o histexpand.o histfile.o histsearch.o shell.o savestring.o \
|
||||
mbutil.o
|
||||
TILDEOBJ = tilde.o
|
||||
OBJECTS = readline.o vi_mode.o funmap.o keymaps.o parens.o search.o \
|
||||
rltty.o complete.o bind.o isearch.o display.o signals.o \
|
||||
util.o kill.o undo.o macro.o input.o callback.o terminal.o \
|
||||
text.o nls.o misc.o $(HISTOBJ) $(TILDEOBJ) xmalloc.o compat.o
|
||||
|
||||
# The texinfo files which document this library.
|
||||
DOCSOURCE = doc/rlman.texinfo doc/rltech.texinfo doc/rluser.texinfo
|
||||
DOCOBJECT = doc/readline.dvi
|
||||
DOCSUPPORT = doc/Makefile
|
||||
DOCUMENTATION = $(DOCSOURCE) $(DOCOBJECT) $(DOCSUPPORT)
|
||||
|
||||
SUPPORT = Makefile ChangeLog $(DOCSUPPORT) examples/[-a-z.]*
|
||||
|
||||
SOURCES = $(CSOURCES) $(HSOURCES) $(DOCSOURCE)
|
||||
|
||||
THINGS_TO_TAR = $(SOURCES) $(SUPPORT)
|
||||
|
||||
INSTALLED_HEADERS = readline.h chardefs.h keymaps.h history.h tilde.h \
|
||||
rlstdc.h rlconf.h rltypedefs.h
|
||||
|
||||
##########################################################################
|
||||
|
||||
all: libreadline.a libhistory.a
|
||||
|
||||
libreadline.a: $(OBJECTS)
|
||||
$(RM) $@
|
||||
$(AR) $(ARFLAGS) $@ $(OBJECTS)
|
||||
-test -n "$(RANLIB)" && $(RANLIB) $@
|
||||
|
||||
libhistory.a: $(HISTOBJ) xmalloc.o
|
||||
$(RM) $@
|
||||
$(AR) $(ARFLAGS) $@ $(HISTOBJ) xmalloc.o
|
||||
-test -n "$(RANLIB)" && $(RANLIB) $@
|
||||
|
||||
documentation: force
|
||||
test -d doc || mkdir doc
|
||||
-( cd doc && $(MAKE) $(MFLAGS) )
|
||||
|
||||
# Since tilde.c is shared between readline and bash, make sure we compile
|
||||
# it with the right flags when it's built as part of readline
|
||||
tilde.o: tilde.c
|
||||
rm -f $@
|
||||
$(CC) $(CCFLAGS) -DREADLINE_LIBRARY -c $(srcdir)/tilde.c
|
||||
|
||||
force:
|
||||
|
||||
install:
|
||||
@echo "This version of the readline library should not be installed."
|
||||
|
||||
uninstall:
|
||||
@echo "This version of the readline library should not be installed."
|
||||
|
||||
TAGS: force
|
||||
$(ETAGS) $(CSOURCES) $(HSOURCES)
|
||||
|
||||
tags: force
|
||||
$(CTAGS) $(CSOURCES) $(HSOURCES)
|
||||
|
||||
clean: force
|
||||
$(RM) $(OBJECTS) *.a
|
||||
-( cd doc && $(MAKE) $(MFLAGS) $@ )
|
||||
|
||||
mostlyclean: clean
|
||||
-( cd doc && $(MAKE) $(MFLAGS) $@ )
|
||||
|
||||
distclean maintainer-clean: clean
|
||||
-( cd doc && $(MAKE) $(MFLAGS) $@ )
|
||||
$(RM) Makefile
|
||||
$(RM) TAGS tags
|
||||
|
||||
# Dependencies
|
||||
bind.o: ansi_stdlib.h posixstat.h
|
||||
bind.o: rldefs.h ${BUILD_DIR}/config.h rlconf.h
|
||||
bind.o: readline.h keymaps.h rltypedefs.h chardefs.h tilde.h
|
||||
bind.o: history.h rlstdc.h
|
||||
callback.o: rlconf.h ansi_stdlib.h
|
||||
callback.o: rldefs.h ${BUILD_DIR}/config.h rlconf.h
|
||||
callback.o: readline.h keymaps.h rltypedefs.h chardefs.h tilde.h rlstdc.h
|
||||
compat.o: rlstdc.h
|
||||
complete.o: ansi_stdlib.h posixdir.h posixstat.h
|
||||
complete.o: rldefs.h ${BUILD_DIR}/config.h rlconf.h
|
||||
complete.o: readline.h keymaps.h rltypedefs.h chardefs.h tilde.h rlstdc.h
|
||||
display.o: ansi_stdlib.h posixstat.h
|
||||
display.o: rldefs.h ${BUILD_DIR}/config.h rlconf.h
|
||||
display.o: tcap.h
|
||||
display.o: readline.h keymaps.h rltypedefs.h chardefs.h tilde.h
|
||||
display.o: history.h rlstdc.h
|
||||
funmap.o: readline.h keymaps.h rltypedefs.h chardefs.h tilde.h
|
||||
funmap.o: rlconf.h ansi_stdlib.h rlstdc.h
|
||||
funmap.o: ${BUILD_DIR}/config.h
|
||||
histexpand.o: ansi_stdlib.h
|
||||
histexpand.o: history.h histlib.h rlstdc.h
|
||||
histexpand.o: ${BUILD_DIR}/config.h
|
||||
histfile.o: ansi_stdlib.h
|
||||
histfile.o: history.h histlib.h rlstdc.h
|
||||
histfile.o: ${BUILD_DIR}/config.h
|
||||
history.o: ansi_stdlib.h
|
||||
history.o: history.h histlib.h rlstdc.h
|
||||
history.o: ${BUILD_DIR}/config.h
|
||||
histsearch.o: ansi_stdlib.h
|
||||
histsearch.o: history.h histlib.h rlstdc.h
|
||||
histsearch.o: ${BUILD_DIR}/config.h
|
||||
input.o: ansi_stdlib.h
|
||||
input.o: rldefs.h ${BUILD_DIR}/config.h rlconf.h
|
||||
input.o: readline.h keymaps.h rltypedefs.h chardefs.h tilde.h rlstdc.h
|
||||
isearch.o: rldefs.h ${BUILD_DIR}/config.h rlconf.h
|
||||
isearch.o: readline.h keymaps.h rltypedefs.h chardefs.h tilde.h
|
||||
isearch.o: ansi_stdlib.h history.h rlstdc.h
|
||||
keymaps.o: emacs_keymap.c vi_keymap.c
|
||||
keymaps.o: keymaps.h rltypedefs.h chardefs.h rlconf.h ansi_stdlib.h
|
||||
keymaps.o: readline.h keymaps.h rltypedefs.h chardefs.h tilde.h
|
||||
keymaps.o: ${BUILD_DIR}/config.h rlstdc.h
|
||||
kill.o: ansi_stdlib.h
|
||||
kill.o: rldefs.h ${BUILD_DIR}/config.h rlconf.h
|
||||
kill.o: readline.h keymaps.h rltypedefs.h chardefs.h tilde.h
|
||||
kill.o: history.h rlstdc.h
|
||||
macro.o: ansi_stdlib.h
|
||||
macro.o: rldefs.h ${BUILD_DIR}/config.h rlconf.h
|
||||
macro.o: readline.h keymaps.h rltypedefs.h chardefs.h tilde.h
|
||||
macro.o: history.h rlstdc.h
|
||||
mbutil.o: rldefs.h ${BUILD_DIR}/config.h rlconf.h rlmbutil.h
|
||||
mbutil.o: readline.h keymaps.h rltypedefs.h chardefs.h rlstdc.h
|
||||
misc.o: readline.h keymaps.h rltypedefs.h chardefs.h tilde.h
|
||||
misc.o: rldefs.h ${BUILD_DIR}/config.h rlconf.h
|
||||
misc.o: history.h rlstdc.h ansi_stdlib.h
|
||||
nls.o: ansi_stdlib.h
|
||||
nls.o: rldefs.h ${BUILD_DIR}/config.h rlconf.h
|
||||
nls.o: readline.h keymaps.h rltypedefs.h chardefs.h tilde.h
|
||||
nls.o: history.h rlstdc.h
|
||||
parens.o: rlconf.h
|
||||
parens.o: ${BUILD_DIR}/config.h
|
||||
parens.o: readline.h keymaps.h rltypedefs.h chardefs.h tilde.h rlstdc.h
|
||||
readline.o: readline.h keymaps.h rltypedefs.h chardefs.h tilde.h
|
||||
readline.o: rldefs.h ${BUILD_DIR}/config.h rlconf.h
|
||||
readline.o: history.h rlstdc.h
|
||||
readline.o: posixstat.h ansi_stdlib.h posixjmp.h
|
||||
rltty.o: rldefs.h ${BUILD_DIR}/config.h rlconf.h
|
||||
rltty.o: rltty.h
|
||||
rltty.o: readline.h keymaps.h rltypedefs.h chardefs.h tilde.h rlstdc.h
|
||||
search.o: rldefs.h ${BUILD_DIR}/config.h rlconf.h
|
||||
search.o: readline.h keymaps.h rltypedefs.h chardefs.h tilde.h
|
||||
search.o: ansi_stdlib.h history.h rlstdc.h
|
||||
shell.o: ${BUILD_DIR}/config.h ansi_stdlib.h
|
||||
signals.o: rldefs.h ${BUILD_DIR}/config.h rlconf.h
|
||||
signals.o: readline.h keymaps.h rltypedefs.h chardefs.h tilde.h
|
||||
signals.o: history.h rlstdc.h
|
||||
terminal.o: rldefs.h ${BUILD_DIR}/config.h rlconf.h
|
||||
terminal.o: tcap.h
|
||||
terminal.o: readline.h keymaps.h rltypedefs.h chardefs.h tilde.h
|
||||
terminal.o: history.h rlstdc.h
|
||||
text.o: readline.h keymaps.h rltypedefs.h chardefs.h tilde.h
|
||||
text.o: rldefs.h ${BUILD_DIR}/config.h rlconf.h
|
||||
text.o: history.h rlstdc.h ansi_stdlib.h
|
||||
rltty.o: rldefs.h ${BUILD_DIR}/config.h rlconf.h
|
||||
tilde.o: ansi_stdlib.h
|
||||
tilde.o: ${BUILD_DIR}/config.h
|
||||
tilde.o: tilde.h
|
||||
undo.o: ansi_stdlib.h
|
||||
undo.o: rldefs.h ${BUILD_DIR}/config.h rlconf.h
|
||||
undo.o: readline.h keymaps.h rltypedefs.h chardefs.h tilde.h
|
||||
undo.o: history.h rlstdc.h xmalloc.h
|
||||
util.o: posixjmp.h ansi_stdlib.h
|
||||
util.o: rldefs.h ${BUILD_DIR}/config.h rlconf.h
|
||||
util.o: readline.h keymaps.h rltypedefs.h chardefs.h tilde.h rlstdc.h
|
||||
vi_mode.o: rldefs.h ${BUILD_DIR}/config.h rlconf.h
|
||||
vi_mode.o: readline.h keymaps.h rltypedefs.h chardefs.h tilde.h
|
||||
vi_mode.o: history.h ansi_stdlib.h rlstdc.h
|
||||
xmalloc.o: ${BUILD_DIR}/config.h ansi_stdlib.h
|
||||
|
||||
bind.o: rlshell.h
|
||||
histfile.o: rlshell.h
|
||||
nls.o: rlshell.h
|
||||
readline.o: rlshell.h
|
||||
shell.o: rlshell.h
|
||||
terminal.o: rlshell.h
|
||||
histexpand.o: rlshell.h
|
||||
|
||||
bind.o: rlprivate.h
|
||||
callback.o: rlprivate.h
|
||||
complete.o: rlprivate.h
|
||||
display.o: rlprivate.h
|
||||
input.o: rlprivate.h
|
||||
isearch.o: rlprivate.h
|
||||
kill.o: rlprivate.h
|
||||
macro.o: rlprivate.h
|
||||
mbutil.o: rlprivate.h
|
||||
misc.o: rlprivate.h
|
||||
nls.o: rlprivate.h
|
||||
parens.o: rlprivate.h
|
||||
readline.o: rlprivate.h
|
||||
rltty.o: rlprivate.h
|
||||
search.o: rlprivate.h
|
||||
signals.o: rlprivate.h
|
||||
terminal.o: rlprivate.h
|
||||
text.o: rlprivate.h
|
||||
undo.o: rlprivate.h
|
||||
util.o: rlprivate.h
|
||||
vi_mode.o: rlprivate.h
|
||||
|
||||
bind.o: xmalloc.h
|
||||
complete.o: xmalloc.h
|
||||
display.o: xmalloc.h
|
||||
funmap.o: xmalloc.h
|
||||
histexpand.o: xmalloc.h
|
||||
histfile.o: xmalloc.h
|
||||
history.o: xmalloc.h
|
||||
input.o: xmalloc.h
|
||||
isearch.o: xmalloc.h
|
||||
keymaps.o: xmalloc.h
|
||||
kill.o: xmalloc.h
|
||||
macro.o: xmalloc.h
|
||||
mbutil.o: xmalloc.h
|
||||
misc.o: xmalloc.h
|
||||
readline.o: xmalloc.h
|
||||
savestring.o: xmalloc.h
|
||||
search.o: xmalloc.h
|
||||
shell.o: xmalloc.h
|
||||
terminal.o: xmalloc.h
|
||||
text.o: xmalloc.h
|
||||
tilde.o: xmalloc.h
|
||||
undo.o: xmalloc.h
|
||||
util.o: xmalloc.h
|
||||
vi_mode.o: xmalloc.h
|
||||
xmalloc.o: xmalloc.h
|
||||
|
||||
complete.o: rlmbutil.h
|
||||
display.o: rlmbutil.h
|
||||
histexpand.o: rlmbutil.h
|
||||
input.o: rlmbutil.h
|
||||
isearch.o: rlmbutil.h
|
||||
mbutil.o: rlmbutil.h
|
||||
misc.o: rlmbutil.h
|
||||
readline.o: rlmbutil.h
|
||||
search.o: rlmbutil.h
|
||||
text.o: rlmbutil.h
|
||||
vi_mode.o: rlmbutil.h
|
||||
|
||||
# Rules for deficient makes, like SunOS and Solaris
|
||||
bind.o: bind.c
|
||||
callback.o: callback.c
|
||||
compat.o: compat.c
|
||||
complete.o: complete.c
|
||||
display.o: display.c
|
||||
funmap.o: funmap.c
|
||||
input.o: input.c
|
||||
isearch.o: isearch.c
|
||||
keymaps.o: keymaps.c emacs_keymap.c vi_keymap.c
|
||||
kill.o: kill.c
|
||||
macro.o: macro.c
|
||||
mbutil.o: mbutil.c
|
||||
misc.o: misc.c
|
||||
nls.o: nls.c
|
||||
parens.o: parens.c
|
||||
readline.o: readline.c
|
||||
rltty.o: rltty.c
|
||||
savestring.o: savestring.c
|
||||
search.o: search.c
|
||||
shell.o: shell.c
|
||||
signals.o: signals.c
|
||||
terminal.o: terminal.c
|
||||
text.o: text.c
|
||||
tilde.o: tilde.c
|
||||
undo.o: undo.c
|
||||
util.o: util.c
|
||||
vi_mode.o: vi_mode.c
|
||||
xmalloc.o: xmalloc.c
|
||||
|
||||
histexpand.o: histexpand.c
|
||||
histfile.o: histfile.c
|
||||
history.o: history.c
|
||||
histsearch.o: histsearch.c
|
||||
@@ -1,6 +1,6 @@
|
||||
/* display.c -- readline redisplay facility. */
|
||||
|
||||
/* Copyright (C) 1987-2004 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library, a library for
|
||||
reading lines of text with interactive input and history editing.
|
||||
|
||||
+11
-1
@@ -1857,12 +1857,17 @@ rl_message (va_alist)
|
||||
#endif
|
||||
va_end (args);
|
||||
|
||||
rl_display_prompt = msg_buf;
|
||||
if (saved_local_prompt == 0)
|
||||
{
|
||||
rl_save_prompt ();
|
||||
msg_saved_prompt = 1;
|
||||
}
|
||||
rl_display_prompt = msg_buf;
|
||||
local_prompt = expand_prompt (msg_buf, &prompt_visible_length,
|
||||
&prompt_last_invisible,
|
||||
&prompt_invis_chars_first_line,
|
||||
&prompt_physical_chars);
|
||||
local_prompt_prefix = (char *)NULL;
|
||||
(*rl_redisplay_function) ();
|
||||
|
||||
return 0;
|
||||
@@ -1881,6 +1886,11 @@ rl_message (format, arg1, arg2)
|
||||
rl_save_prompt ();
|
||||
msg_saved_prompt = 1;
|
||||
}
|
||||
local_prompt = expand_prompt (msg_buf, &prompt_visible_length,
|
||||
&prompt_last_invisible,
|
||||
&prompt_invis_chars_first_line,
|
||||
&prompt_physical_chars);
|
||||
local_prompt_prefix = (char *)NULL;
|
||||
(*rl_redisplay_function) ();
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* history.c -- standalone history library */
|
||||
|
||||
/* Copyright (C) 1989-2003 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1989-2005 Free Software Foundation, Inc.
|
||||
|
||||
This file contains the GNU History Library (the Library), a set of
|
||||
routines for managing the text of previously typed lines.
|
||||
|
||||
@@ -0,0 +1,441 @@
|
||||
/* history.c -- standalone history library */
|
||||
|
||||
/* Copyright (C) 1989-2003 Free Software Foundation, Inc.
|
||||
|
||||
This file contains the GNU History Library (the Library), a set of
|
||||
routines for managing the text of previously typed lines.
|
||||
|
||||
The Library 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.
|
||||
|
||||
The Library 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.
|
||||
|
||||
The GNU General Public License is often shipped with GNU software, and
|
||||
is generally kept in a file called COPYING or LICENSE. If you do not
|
||||
have a copy of the license, write to the Free Software Foundation,
|
||||
59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
/* The goal is to make the implementation transparent, so that you
|
||||
don't have to know what data types are used, just what functions
|
||||
you can call. I think I have done that. */
|
||||
#define READLINE_LIBRARY
|
||||
|
||||
#if defined (HAVE_CONFIG_H)
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined (HAVE_STDLIB_H)
|
||||
# include <stdlib.h>
|
||||
#else
|
||||
# include "ansi_stdlib.h"
|
||||
#endif /* HAVE_STDLIB_H */
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# ifdef _MINIX
|
||||
# include <sys/types.h>
|
||||
# endif
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "history.h"
|
||||
#include "histlib.h"
|
||||
|
||||
#include "xmalloc.h"
|
||||
|
||||
/* The number of slots to increase the_history by. */
|
||||
#define DEFAULT_HISTORY_GROW_SIZE 50
|
||||
|
||||
static char *hist_inittime PARAMS((void));
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* History Functions */
|
||||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
/* An array of HIST_ENTRY. This is where we store the history. */
|
||||
static HIST_ENTRY **the_history = (HIST_ENTRY **)NULL;
|
||||
|
||||
/* Non-zero means that we have enforced a limit on the amount of
|
||||
history that we save. */
|
||||
static int history_stifled;
|
||||
|
||||
/* The current number of slots allocated to the input_history. */
|
||||
static int history_size;
|
||||
|
||||
/* If HISTORY_STIFLED is non-zero, then this is the maximum number of
|
||||
entries to remember. */
|
||||
int history_max_entries;
|
||||
int max_input_history; /* backwards compatibility */
|
||||
|
||||
/* The current location of the interactive history pointer. Just makes
|
||||
life easier for outside callers. */
|
||||
int history_offset;
|
||||
|
||||
/* The number of strings currently stored in the history list. */
|
||||
int history_length;
|
||||
|
||||
/* The logical `base' of the history array. It defaults to 1. */
|
||||
int history_base = 1;
|
||||
|
||||
/* Return the current HISTORY_STATE of the history. */
|
||||
HISTORY_STATE *
|
||||
history_get_history_state ()
|
||||
{
|
||||
HISTORY_STATE *state;
|
||||
|
||||
state = (HISTORY_STATE *)xmalloc (sizeof (HISTORY_STATE));
|
||||
state->entries = the_history;
|
||||
state->offset = history_offset;
|
||||
state->length = history_length;
|
||||
state->size = history_size;
|
||||
state->flags = 0;
|
||||
if (history_stifled)
|
||||
state->flags |= HS_STIFLED;
|
||||
|
||||
return (state);
|
||||
}
|
||||
|
||||
/* Set the state of the current history array to STATE. */
|
||||
void
|
||||
history_set_history_state (state)
|
||||
HISTORY_STATE *state;
|
||||
{
|
||||
the_history = state->entries;
|
||||
history_offset = state->offset;
|
||||
history_length = state->length;
|
||||
history_size = state->size;
|
||||
if (state->flags & HS_STIFLED)
|
||||
history_stifled = 1;
|
||||
}
|
||||
|
||||
/* Begin a session in which the history functions might be used. This
|
||||
initializes interactive variables. */
|
||||
void
|
||||
using_history ()
|
||||
{
|
||||
history_offset = history_length;
|
||||
}
|
||||
|
||||
/* Return the number of bytes that the primary history entries are using.
|
||||
This just adds up the lengths of the_history->lines and the associated
|
||||
timestamps. */
|
||||
int
|
||||
history_total_bytes ()
|
||||
{
|
||||
register int i, result;
|
||||
|
||||
for (i = result = 0; the_history && the_history[i]; i++)
|
||||
result += HISTENT_BYTES (the_history[i]);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
/* Returns the magic number which says what history element we are
|
||||
looking at now. In this implementation, it returns history_offset. */
|
||||
int
|
||||
where_history ()
|
||||
{
|
||||
return (history_offset);
|
||||
}
|
||||
|
||||
/* Make the current history item be the one at POS, an absolute index.
|
||||
Returns zero if POS is out of range, else non-zero. */
|
||||
int
|
||||
history_set_pos (pos)
|
||||
int pos;
|
||||
{
|
||||
if (pos > history_length || pos < 0 || !the_history)
|
||||
return (0);
|
||||
history_offset = pos;
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* Return the current history array. The caller has to be carefull, since this
|
||||
is the actual array of data, and could be bashed or made corrupt easily.
|
||||
The array is terminated with a NULL pointer. */
|
||||
HIST_ENTRY **
|
||||
history_list ()
|
||||
{
|
||||
return (the_history);
|
||||
}
|
||||
|
||||
/* Return the history entry at the current position, as determined by
|
||||
history_offset. If there is no entry there, return a NULL pointer. */
|
||||
HIST_ENTRY *
|
||||
current_history ()
|
||||
{
|
||||
return ((history_offset == history_length) || the_history == 0)
|
||||
? (HIST_ENTRY *)NULL
|
||||
: the_history[history_offset];
|
||||
}
|
||||
|
||||
/* Back up history_offset to the previous history entry, and return
|
||||
a pointer to that entry. If there is no previous entry then return
|
||||
a NULL pointer. */
|
||||
HIST_ENTRY *
|
||||
previous_history ()
|
||||
{
|
||||
return history_offset ? the_history[--history_offset] : (HIST_ENTRY *)NULL;
|
||||
}
|
||||
|
||||
/* Move history_offset forward to the next history entry, and return
|
||||
a pointer to that entry. If there is no next entry then return a
|
||||
NULL pointer. */
|
||||
HIST_ENTRY *
|
||||
next_history ()
|
||||
{
|
||||
return (history_offset == history_length) ? (HIST_ENTRY *)NULL : the_history[++history_offset];
|
||||
}
|
||||
|
||||
/* Return the history entry which is logically at OFFSET in the history array.
|
||||
OFFSET is relative to history_base. */
|
||||
HIST_ENTRY *
|
||||
history_get (offset)
|
||||
int offset;
|
||||
{
|
||||
int local_index;
|
||||
|
||||
local_index = offset - history_base;
|
||||
return (local_index >= history_length || local_index < 0 || !the_history)
|
||||
? (HIST_ENTRY *)NULL
|
||||
: the_history[local_index];
|
||||
}
|
||||
|
||||
time_t
|
||||
history_get_time (hist)
|
||||
HIST_ENTRY *hist;
|
||||
{
|
||||
char *ts;
|
||||
time_t t;
|
||||
|
||||
if (hist == 0 || hist->timestamp == 0)
|
||||
return 0;
|
||||
ts = hist->timestamp;
|
||||
if (ts[0] != history_comment_char)
|
||||
return 0;
|
||||
t = (time_t) atol (ts + 1); /* XXX - should use strtol() here */
|
||||
return t;
|
||||
}
|
||||
|
||||
static char *
|
||||
hist_inittime ()
|
||||
{
|
||||
time_t t;
|
||||
char ts[64], *ret;
|
||||
|
||||
t = (time_t) time ((time_t *)0);
|
||||
#if defined (HAVE_VSNPRINTF) /* assume snprintf if vsnprintf exists */
|
||||
snprintf (ts, sizeof (ts) - 1, "X%lu", (unsigned long) t);
|
||||
#else
|
||||
sprintf (ts, "X%lu", (unsigned long) t);
|
||||
#endif
|
||||
ret = savestring (ts);
|
||||
ret[0] = history_comment_char;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Place STRING at the end of the history list. The data field
|
||||
is set to NULL. */
|
||||
void
|
||||
add_history (string)
|
||||
const char *string;
|
||||
{
|
||||
HIST_ENTRY *temp;
|
||||
|
||||
if (history_stifled && (history_length == history_max_entries))
|
||||
{
|
||||
register int i;
|
||||
|
||||
/* If the history is stifled, and history_length is zero,
|
||||
and it equals history_max_entries, we don't save items. */
|
||||
if (history_length == 0)
|
||||
return;
|
||||
|
||||
/* If there is something in the slot, then remove it. */
|
||||
if (the_history[0])
|
||||
(void) free_history_entry (the_history[0]);
|
||||
|
||||
/* Copy the rest of the entries, moving down one slot. */
|
||||
for (i = 0; i < history_length; i++)
|
||||
the_history[i] = the_history[i + 1];
|
||||
|
||||
history_base++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (history_size == 0)
|
||||
{
|
||||
history_size = DEFAULT_HISTORY_GROW_SIZE;
|
||||
the_history = (HIST_ENTRY **)xmalloc (history_size * sizeof (HIST_ENTRY *));
|
||||
history_length = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (history_length == (history_size - 1))
|
||||
{
|
||||
history_size += DEFAULT_HISTORY_GROW_SIZE;
|
||||
the_history = (HIST_ENTRY **)
|
||||
xrealloc (the_history, history_size * sizeof (HIST_ENTRY *));
|
||||
}
|
||||
history_length++;
|
||||
}
|
||||
}
|
||||
|
||||
temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
|
||||
temp->line = savestring (string);
|
||||
temp->data = (char *)NULL;
|
||||
|
||||
temp->timestamp = hist_inittime ();
|
||||
|
||||
the_history[history_length] = (HIST_ENTRY *)NULL;
|
||||
the_history[history_length - 1] = temp;
|
||||
}
|
||||
|
||||
/* Change the time stamp of the most recent history entry to STRING. */
|
||||
void
|
||||
add_history_time (string)
|
||||
const char *string;
|
||||
{
|
||||
HIST_ENTRY *hs;
|
||||
|
||||
hs = the_history[history_length - 1];
|
||||
FREE (hs->timestamp);
|
||||
hs->timestamp = savestring (string);
|
||||
}
|
||||
|
||||
/* Free HIST and return the data so the calling application can free it
|
||||
if necessary and desired. */
|
||||
histdata_t
|
||||
free_history_entry (hist)
|
||||
HIST_ENTRY *hist;
|
||||
{
|
||||
histdata_t x;
|
||||
|
||||
if (hist == 0)
|
||||
return ((histdata_t) 0);
|
||||
FREE (hist->line);
|
||||
FREE (hist->timestamp);
|
||||
x = hist->data;
|
||||
free (hist);
|
||||
return (x);
|
||||
}
|
||||
|
||||
/* Make the history entry at WHICH have LINE and DATA. This returns
|
||||
the old entry so you can dispose of the data. In the case of an
|
||||
invalid WHICH, a NULL pointer is returned. */
|
||||
HIST_ENTRY *
|
||||
replace_history_entry (which, line, data)
|
||||
int which;
|
||||
const char *line;
|
||||
histdata_t data;
|
||||
{
|
||||
HIST_ENTRY *temp, *old_value;
|
||||
|
||||
if (which < 0 || which >= history_length)
|
||||
return ((HIST_ENTRY *)NULL);
|
||||
|
||||
temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
|
||||
old_value = the_history[which];
|
||||
|
||||
temp->line = savestring (line);
|
||||
temp->data = data;
|
||||
temp->timestamp = savestring (old_value->timestamp);
|
||||
the_history[which] = temp;
|
||||
|
||||
return (old_value);
|
||||
}
|
||||
|
||||
/* Remove history element WHICH from the history. The removed
|
||||
element is returned to you so you can free the line, data,
|
||||
and containing structure. */
|
||||
HIST_ENTRY *
|
||||
remove_history (which)
|
||||
int which;
|
||||
{
|
||||
HIST_ENTRY *return_value;
|
||||
register int i;
|
||||
|
||||
if (which < 0 || which >= history_length || history_length == 0)
|
||||
return ((HIST_ENTRY *)NULL);
|
||||
|
||||
return_value = the_history[which];
|
||||
|
||||
for (i = which; i < history_length; i++)
|
||||
the_history[i] = the_history[i + 1];
|
||||
|
||||
history_length--;
|
||||
|
||||
return (return_value);
|
||||
}
|
||||
|
||||
/* Stifle the history list, remembering only MAX number of lines. */
|
||||
void
|
||||
stifle_history (max)
|
||||
int max;
|
||||
{
|
||||
register int i, j;
|
||||
|
||||
if (max < 0)
|
||||
max = 0;
|
||||
|
||||
if (history_length > max)
|
||||
{
|
||||
/* This loses because we cannot free the data. */
|
||||
for (i = 0, j = history_length - max; i < j; i++)
|
||||
free_history_entry (the_history[i]);
|
||||
|
||||
history_base = i;
|
||||
for (j = 0, i = history_length - max; j < max; i++, j++)
|
||||
the_history[j] = the_history[i];
|
||||
the_history[j] = (HIST_ENTRY *)NULL;
|
||||
history_length = j;
|
||||
}
|
||||
|
||||
history_stifled = 1;
|
||||
max_input_history = history_max_entries = max;
|
||||
}
|
||||
|
||||
/* Stop stifling the history. This returns the previous maximum
|
||||
number of history entries. The value is positive if the history
|
||||
was stifled, negative if it wasn't. */
|
||||
int
|
||||
unstifle_history ()
|
||||
{
|
||||
if (history_stifled)
|
||||
{
|
||||
history_stifled = 0;
|
||||
return (history_max_entries);
|
||||
}
|
||||
else
|
||||
return (-history_max_entries);
|
||||
}
|
||||
|
||||
int
|
||||
history_is_stifled ()
|
||||
{
|
||||
return (history_stifled);
|
||||
}
|
||||
|
||||
void
|
||||
clear_history ()
|
||||
{
|
||||
register int i;
|
||||
|
||||
/* This loses because we cannot free the data. */
|
||||
for (i = 0; i < history_length; i++)
|
||||
{
|
||||
free_history_entry (the_history[i]);
|
||||
the_history[i] = (HIST_ENTRY *)NULL;
|
||||
}
|
||||
|
||||
history_offset = history_length = 0;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/* mbutil.c -- readline multibyte character utility functions */
|
||||
|
||||
/* Copyright (C) 2001-2004 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2001-2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library, a library for
|
||||
reading lines of text with interactive input and history editing.
|
||||
|
||||
@@ -77,18 +77,20 @@ _rl_find_next_mbchar_internal (string, seed, count, find_non_zero)
|
||||
char *string;
|
||||
int seed, count, find_non_zero;
|
||||
{
|
||||
size_t tmp = 0;
|
||||
size_t tmp;
|
||||
mbstate_t ps;
|
||||
int point = 0;
|
||||
int point;
|
||||
wchar_t wc;
|
||||
|
||||
tmp = 0;
|
||||
|
||||
memset(&ps, 0, sizeof (mbstate_t));
|
||||
if (seed < 0)
|
||||
seed = 0;
|
||||
if (count <= 0)
|
||||
return seed;
|
||||
|
||||
point = seed + _rl_adjust_point(string, seed, &ps);
|
||||
point = seed + _rl_adjust_point (string, seed, &ps);
|
||||
/* if this is true, means that seed was not pointed character
|
||||
started byte. So correct the point and consume count */
|
||||
if (seed < point)
|
||||
@@ -134,7 +136,8 @@ _rl_find_next_mbchar_internal (string, seed, count, find_non_zero)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return point;
|
||||
|
||||
return point;
|
||||
}
|
||||
|
||||
static int
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* readline.c -- a general facility for reading lines of input
|
||||
with emacs style editing and completion. */
|
||||
|
||||
/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library, a library for
|
||||
reading lines of text with interactive input and history editing.
|
||||
|
||||
@@ -656,11 +656,6 @@ _rl_dispatch_subseq (key, map, got_subseq)
|
||||
already taken care of pushing any necessary input back onto
|
||||
the input queue with _rl_unget_char. */
|
||||
{
|
||||
#if 0
|
||||
r = _rl_dispatch (ANYOTHERKEY, FUNCTION_TO_KEYMAP (map, key));
|
||||
#else
|
||||
/* XXX - experimental code -- might never be executed. Save
|
||||
for later. */
|
||||
Keymap m = FUNCTION_TO_KEYMAP (map, key);
|
||||
int type = m[ANYOTHERKEY].type;
|
||||
func = m[ANYOTHERKEY].function;
|
||||
@@ -682,7 +677,6 @@ _rl_dispatch_subseq (key, map, got_subseq)
|
||||
}
|
||||
else
|
||||
r = _rl_dispatch (ANYOTHERKEY, m);
|
||||
#endif
|
||||
}
|
||||
else if (r && map[ANYOTHERKEY].function)
|
||||
{
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
# Makefile for the Bash library
|
||||
#
|
||||
#
|
||||
# Copyright (C) 1998-2002 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1998-2005 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
|
||||
|
||||
+6
-2
@@ -86,7 +86,7 @@ CSOURCES = clktck.c clock.c getcwd.c getenv.c oslib.c setlinebuf.c \
|
||||
inet_aton.c netconn.c netopen.c strpbrk.c timeval.c makepath.c \
|
||||
pathcanon.c pathphys.c tmpfile.c stringlist.c stringvec.c spell.c \
|
||||
shquote.c strtrans.c strindex.c snprintf.c mailstat.c \
|
||||
fmtulong.c fmtullong.c fmtumax.c shmatch.c \
|
||||
fmtulong.c fmtullong.c fmtumax.c shmatch.c strnlen.c \
|
||||
strtoll.c strtoull.c strtoimax.c strtoumax.c memset.c strstr.c \
|
||||
mktime.c strftime.c xstrchr.c zcatfd.c
|
||||
|
||||
@@ -95,7 +95,7 @@ HSOURCES =
|
||||
|
||||
# The object files contained in $(LIBRARY_NAME)
|
||||
LIBOBJS = @LIBOBJS@
|
||||
OBJECTS = clktck.o clock.o getenv.o oslib.o setlinebuf.o \
|
||||
OBJECTS = clktck.o clock.o getenv.o oslib.o setlinebuf.o strnlen.o \
|
||||
itos.o zread.o zwrite.o shtty.o shmatch.o \
|
||||
netconn.o netopen.o timeval.o makepath.o pathcanon.o \
|
||||
pathphys.o tmpfile.o stringlist.o stringvec.o spell.o shquote.o \
|
||||
@@ -162,6 +162,7 @@ strftime.o: strftime.c
|
||||
strindex.o: strindex.c
|
||||
stringlist.o: stringlist.c
|
||||
stringvec.o: stringvec.c
|
||||
strnlen.o: strnlen.c
|
||||
strpbrk.o: strpbrk.c
|
||||
strtod.o: strtod.c
|
||||
strtoimax.o: strtoimax.c
|
||||
@@ -218,6 +219,7 @@ strftime.o: ${BUILD_DIR}/config.h
|
||||
strindex.o: ${BUILD_DIR}/config.h
|
||||
stringlist.o: ${BUILD_DIR}/config.h
|
||||
stringvec.o: ${BUILD_DIR}/config.h
|
||||
strnlen.o: ${BUILD_DIR}/config.h
|
||||
strpbrk.o: ${BUILD_DIR}/config.h
|
||||
strtod.o: ${BUILD_DIR}/config.h
|
||||
strtoimax.o: ${BUILD_DIR}/config.h
|
||||
@@ -372,6 +374,8 @@ stringvec.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
|
||||
stringvec.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
|
||||
stringvec.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
|
||||
|
||||
strnlen.o: ${BASHINCDIR}/stdc.h
|
||||
|
||||
strpbrk.o: ${BASHINCDIR}/stdc.h
|
||||
|
||||
strtod.o: ${topdir}/bashansi.h
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
/* netconn.c -- is a particular file descriptor a network connection?. */
|
||||
|
||||
/* Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2002-2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
+2
-2
@@ -52,8 +52,8 @@ isnetconn (fd)
|
||||
|
||||
l = sizeof(sa);
|
||||
rv = getpeername(fd, &sa, &l);
|
||||
/* Solaris 2.5 getpeername() returns EINVAL if the fd is not a socket. */
|
||||
return ((rv < 0 && (errno == ENOTSOCK || errno == EINVAL)) ? 0 : 1);
|
||||
/* Posix.2 says getpeername can return these errors. */
|
||||
return ((rv < 0 && (errno == ENOTSOCK || errno == ENOTCONN || errno == EINVAL)) ? 0 : 1);
|
||||
#else /* !HAVE_GETPEERNAME || SVR4_2 || __BEOS__ */
|
||||
# if defined (SVR4) || defined (SVR4_2)
|
||||
/* Sockets on SVR4 and SVR4.2 are character special (streams) devices. */
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
# #
|
||||
####################################################################
|
||||
|
||||
# Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1996-2005 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
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
## -*- text -*- ####################################################
|
||||
# #
|
||||
# Makefile for termcap replacement libbrary. #
|
||||
# #
|
||||
####################################################################
|
||||
|
||||
# Copyright (C) 1996 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
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program 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 this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = .:@srcdir@
|
||||
topdir = @top_srcdir@
|
||||
BUILD_DIR = @BUILD_DIR@
|
||||
|
||||
libdir = @libdir@
|
||||
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
|
||||
CC = @CC@
|
||||
RANLIB = @RANLIB@
|
||||
AR = @AR@
|
||||
ARFLAGS = @ARFLAGS@
|
||||
RM = rm -f
|
||||
CP = cp
|
||||
MV = mv
|
||||
|
||||
SHELL = @MAKE_SHELL@
|
||||
|
||||
CFLAGS = @CFLAGS@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
DEFS = @DEFS@
|
||||
|
||||
INCLUDES = -I. -I../.. -I$(topdir) -I$(topdir)/lib -I$(srcdir)
|
||||
|
||||
CCFLAGS = $(CFLAGS) $(DEFS) $(CPPFLAGS) ${INCLUDES}
|
||||
|
||||
# Here is a rule for making .o files from .c files that doesn't force
|
||||
# the type of the machine (like -sun3) into the flags.
|
||||
.c.o:
|
||||
$(CC) -c $(CCFLAGS) $<
|
||||
|
||||
SOURCES = termcap.c tparam.c
|
||||
OBJECTS = termcap.o tparam.o
|
||||
|
||||
DOCUMENTATION = termcap.texinfo
|
||||
|
||||
THINGS_TO_TAR = $(SOURCES) $(DOCUMENTATION)
|
||||
|
||||
##########################################################################
|
||||
|
||||
all: libtermcap.a
|
||||
|
||||
libtermcap.a: $(OBJECTS)
|
||||
$(RM) -f $@
|
||||
$(AR) $(ARFLAGS) $@ $(OBJECTS)
|
||||
-test -n "$(RANLIB)" && $(RANLIB) $@
|
||||
|
||||
install:
|
||||
|
||||
clean:
|
||||
$(RM) *.o *.a *.log *.cp *.tp *.vr *.fn *.aux *.pg *.toc
|
||||
|
||||
mostlyclean: clean
|
||||
|
||||
distclean maintainer-clean: clean
|
||||
$(RM) Makefile
|
||||
|
||||
$(DESTDIR)$(libdir)/libtermcap.a: libtermcap.a
|
||||
${INSTALL_DATA} -c -m 644 libtermcap.a $@
|
||||
-test -n "$(RANLIB)" && $(RANLIB) -t $@
|
||||
|
||||
termcap.o: $(BUILD_DIR)/config.h
|
||||
tparam.o: $(BUILD_DIR)/config.h
|
||||
version.o: $(BUILD_DIR)/config.h
|
||||
@@ -4,7 +4,7 @@
|
||||
# #
|
||||
####################################################################
|
||||
|
||||
# Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1996-2005 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
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
## -*- text -*- ####################################################
|
||||
# #
|
||||
# Makefile for the GNU Tilde Library. #
|
||||
# #
|
||||
####################################################################
|
||||
|
||||
# Copyright (C) 1996 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
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program 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 this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = .:@srcdir@
|
||||
topdir = @top_srcdir@
|
||||
BUILD_DIR = @BUILD_DIR@
|
||||
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
|
||||
CC = @CC@
|
||||
RANLIB = @RANLIB@
|
||||
AR = @AR@
|
||||
ARFLAGS = @ARFLAGS@
|
||||
RM = rm
|
||||
CP = cp
|
||||
MV = mv
|
||||
|
||||
SHELL = @MAKE_SHELL@
|
||||
|
||||
PROFILE_FLAGS = @PROFILE_FLAGS@
|
||||
|
||||
CFLAGS = @CFLAGS@
|
||||
LOCAL_CFLAGS = @LOCAL_CFLAGS@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
LDFLAGS = @LDFLAGS@ @LOCAL_LDFLAGS@
|
||||
|
||||
DEFS = @DEFS@
|
||||
LOCAL_DEFS = @LOCAL_DEFS@
|
||||
|
||||
BASHINCDIR = ${topdir}/include
|
||||
|
||||
INCLUDES = -I. -I../.. -I$(topdir) -I${BASHINCDIR} -I$(topdir)/lib
|
||||
|
||||
CCFLAGS = $(PROFILE_FLAGS) $(DEFS) $(LOCAL_DEFS) $(CPPFLAGS) \
|
||||
${INCLUDES} $(LOCAL_CFLAGS) $(CFLAGS)
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CCFLAGS) $<
|
||||
|
||||
# The name of the library target.
|
||||
LIBRARY_NAME = libtilde.a
|
||||
|
||||
# The C code source files for this library.
|
||||
CSOURCES = $(srcdir)/tilde.c
|
||||
|
||||
# The header files for this library.
|
||||
HSOURCES = $(srcdir)/tilde.h
|
||||
|
||||
OBJECTS = tilde.o
|
||||
|
||||
# The texinfo files which document this library.
|
||||
DOCSOURCE = doc/tilde.texi
|
||||
DOCOBJECT = doc/tilde.dvi
|
||||
DOCSUPPORT = doc/Makefile
|
||||
DOCUMENTATION = $(DOCSOURCE) $(DOCOBJECT) $(DOCSUPPORT)
|
||||
|
||||
SUPPORT = Makefile ChangeLog $(DOCSUPPORT)
|
||||
|
||||
SOURCES = $(CSOURCES) $(HSOURCES) $(DOCSOURCE)
|
||||
|
||||
THINGS_TO_TAR = $(SOURCES) $(SUPPORT)
|
||||
|
||||
######################################################################
|
||||
|
||||
all: $(LIBRARY_NAME)
|
||||
|
||||
$(LIBRARY_NAME): $(OBJECTS)
|
||||
$(RM) -f $@
|
||||
$(AR) $(ARFLAGS) $@ $(OBJECTS)
|
||||
-test -n "$(RANLIB)" && $(RANLIB) $@
|
||||
|
||||
documentation: force
|
||||
-(cd doc; $(MAKE) $(MFLAGS))
|
||||
|
||||
force:
|
||||
|
||||
# The rule for 'includes' is written funny so that the if statement
|
||||
# always returns TRUE unless there really was an error installing the
|
||||
# include files.
|
||||
install:
|
||||
$(INSTALL_DATA) -c -m 644 $(LIBRARY_NAME) $(libdir)/$(LIBRARY_NAME)
|
||||
-test -n "$(RANLIB)" && $(RANLIB) -t $(libdir)/$(LIBRARY_NAME)
|
||||
|
||||
clean:
|
||||
$(RM) -f $(OBJECTS) $(LIBRARY_NAME)
|
||||
-( cd doc && $(MAKE) $(MFLAGS) $@ )
|
||||
|
||||
realclean distclean maintainer-clean: clean
|
||||
-( cd doc && $(MAKE) $(MFLAGS) $@ )
|
||||
$(RM) -f Makefile
|
||||
|
||||
mostlyclean: clean
|
||||
-( cd doc && $(MAKE) $(MFLAGS) $@ )
|
||||
|
||||
######################################################################
|
||||
# #
|
||||
# Dependencies for the object files which make up this library. #
|
||||
# #
|
||||
######################################################################
|
||||
|
||||
tilde.o: tilde.h $(BASHINCDIR)/ansi_stdlib.h
|
||||
tilde.o: $(BUILD_DIR)/config.h
|
||||
|
||||
# Rules for deficient makes, like SunOS and Solaris
|
||||
tilde.o: tilde.c
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
/* make_cmd.c -- Functions for making instances of the various
|
||||
parser constructs. */
|
||||
|
||||
/* Copyright (C) 1989-2003 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1989-2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
+851
@@ -0,0 +1,851 @@
|
||||
/* make_cmd.c -- Functions for making instances of the various
|
||||
parser constructs. */
|
||||
|
||||
/* Copyright (C) 1989-2003 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. */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include "bashtypes.h"
|
||||
#if !defined (_MINIX) && defined (HAVE_SYS_FILE_H)
|
||||
# include <sys/file.h>
|
||||
#endif
|
||||
#include "filecntl.h"
|
||||
#include "bashansi.h"
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "bashintl.h"
|
||||
|
||||
#include "syntax.h"
|
||||
#include "command.h"
|
||||
#include "general.h"
|
||||
#include "error.h"
|
||||
#include "flags.h"
|
||||
#include "make_cmd.h"
|
||||
#include "dispose_cmd.h"
|
||||
#include "variables.h"
|
||||
#include "subst.h"
|
||||
#include "input.h"
|
||||
#include "ocache.h"
|
||||
#include "externs.h"
|
||||
|
||||
#if defined (JOB_CONTROL)
|
||||
#include "jobs.h"
|
||||
#endif
|
||||
|
||||
#include "shmbutil.h"
|
||||
|
||||
extern int line_number, current_command_line_count;
|
||||
extern int last_command_exit_value;
|
||||
|
||||
/* Object caching */
|
||||
sh_obj_cache_t wdcache = {0, 0, 0};
|
||||
sh_obj_cache_t wlcache = {0, 0, 0};
|
||||
|
||||
#define WDCACHESIZE 60
|
||||
#define WLCACHESIZE 60
|
||||
|
||||
static COMMAND *make_for_or_select __P((enum command_type, WORD_DESC *, WORD_LIST *, COMMAND *, int));
|
||||
#if defined (ARITH_FOR_COMMAND)
|
||||
static WORD_LIST *make_arith_for_expr __P((char *));
|
||||
#endif
|
||||
static COMMAND *make_until_or_while __P((enum command_type, COMMAND *, COMMAND *));
|
||||
|
||||
void
|
||||
cmd_init ()
|
||||
{
|
||||
ocache_create (wdcache, WORD_DESC, WDCACHESIZE);
|
||||
ocache_create (wlcache, WORD_LIST, WLCACHESIZE);
|
||||
}
|
||||
|
||||
WORD_DESC *
|
||||
alloc_word_desc ()
|
||||
{
|
||||
WORD_DESC *temp;
|
||||
|
||||
ocache_alloc (wdcache, WORD_DESC, temp);
|
||||
temp->flags = 0;
|
||||
temp->word = 0;
|
||||
return temp;
|
||||
}
|
||||
|
||||
WORD_DESC *
|
||||
make_bare_word (string)
|
||||
const char *string;
|
||||
{
|
||||
WORD_DESC *temp;
|
||||
|
||||
temp = alloc_word_desc ();
|
||||
|
||||
if (*string)
|
||||
temp->word = savestring (string);
|
||||
else
|
||||
{
|
||||
temp->word = (char *)xmalloc (1);
|
||||
temp->word[0] = '\0';
|
||||
}
|
||||
|
||||
return (temp);
|
||||
}
|
||||
|
||||
WORD_DESC *
|
||||
make_word_flags (w, string)
|
||||
WORD_DESC *w;
|
||||
const char *string;
|
||||
{
|
||||
register int i;
|
||||
size_t slen;
|
||||
DECLARE_MBSTATE;
|
||||
|
||||
i = 0;
|
||||
slen = strlen (string);
|
||||
while (i < slen)
|
||||
{
|
||||
switch (string[i])
|
||||
{
|
||||
case '$':
|
||||
w->flags |= W_HASDOLLAR;
|
||||
break;
|
||||
case '\\':
|
||||
break; /* continue the loop */
|
||||
case '\'':
|
||||
case '`':
|
||||
case '"':
|
||||
w->flags |= W_QUOTED;
|
||||
break;
|
||||
}
|
||||
|
||||
ADVANCE_CHAR (string, slen, i);
|
||||
}
|
||||
|
||||
return (w);
|
||||
}
|
||||
|
||||
WORD_DESC *
|
||||
make_word (string)
|
||||
const char *string;
|
||||
{
|
||||
WORD_DESC *temp;
|
||||
|
||||
temp = make_bare_word (string);
|
||||
return (make_word_flags (temp, string));
|
||||
}
|
||||
|
||||
WORD_DESC *
|
||||
make_word_from_token (token)
|
||||
int token;
|
||||
{
|
||||
char tokenizer[2];
|
||||
|
||||
tokenizer[0] = token;
|
||||
tokenizer[1] = '\0';
|
||||
|
||||
return (make_word (tokenizer));
|
||||
}
|
||||
|
||||
WORD_LIST *
|
||||
make_word_list (word, wlink)
|
||||
WORD_DESC *word;
|
||||
WORD_LIST *wlink;
|
||||
{
|
||||
WORD_LIST *temp;
|
||||
|
||||
ocache_alloc (wlcache, WORD_LIST, temp);
|
||||
|
||||
temp->word = word;
|
||||
temp->next = wlink;
|
||||
return (temp);
|
||||
}
|
||||
|
||||
COMMAND *
|
||||
make_command (type, pointer)
|
||||
enum command_type type;
|
||||
SIMPLE_COM *pointer;
|
||||
{
|
||||
COMMAND *temp;
|
||||
|
||||
temp = (COMMAND *)xmalloc (sizeof (COMMAND));
|
||||
temp->type = type;
|
||||
temp->value.Simple = pointer;
|
||||
temp->value.Simple->flags = temp->flags = 0;
|
||||
temp->redirects = (REDIRECT *)NULL;
|
||||
return (temp);
|
||||
}
|
||||
|
||||
COMMAND *
|
||||
command_connect (com1, com2, connector)
|
||||
COMMAND *com1, *com2;
|
||||
int connector;
|
||||
{
|
||||
CONNECTION *temp;
|
||||
|
||||
temp = (CONNECTION *)xmalloc (sizeof (CONNECTION));
|
||||
temp->connector = connector;
|
||||
temp->first = com1;
|
||||
temp->second = com2;
|
||||
return (make_command (cm_connection, (SIMPLE_COM *)temp));
|
||||
}
|
||||
|
||||
static COMMAND *
|
||||
make_for_or_select (type, name, map_list, action, lineno)
|
||||
enum command_type type;
|
||||
WORD_DESC *name;
|
||||
WORD_LIST *map_list;
|
||||
COMMAND *action;
|
||||
int lineno;
|
||||
{
|
||||
FOR_COM *temp;
|
||||
|
||||
temp = (FOR_COM *)xmalloc (sizeof (FOR_COM));
|
||||
temp->flags = 0;
|
||||
temp->name = name;
|
||||
temp->line = lineno;
|
||||
temp->map_list = map_list;
|
||||
temp->action = action;
|
||||
return (make_command (type, (SIMPLE_COM *)temp));
|
||||
}
|
||||
|
||||
COMMAND *
|
||||
make_for_command (name, map_list, action, lineno)
|
||||
WORD_DESC *name;
|
||||
WORD_LIST *map_list;
|
||||
COMMAND *action;
|
||||
int lineno;
|
||||
{
|
||||
return (make_for_or_select (cm_for, name, map_list, action, lineno));
|
||||
}
|
||||
|
||||
COMMAND *
|
||||
make_select_command (name, map_list, action, lineno)
|
||||
WORD_DESC *name;
|
||||
WORD_LIST *map_list;
|
||||
COMMAND *action;
|
||||
int lineno;
|
||||
{
|
||||
#if defined (SELECT_COMMAND)
|
||||
return (make_for_or_select (cm_select, name, map_list, action, lineno));
|
||||
#else
|
||||
last_command_exit_value = 2;
|
||||
return ((COMMAND *)NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined (ARITH_FOR_COMMAND)
|
||||
static WORD_LIST *
|
||||
make_arith_for_expr (s)
|
||||
char *s;
|
||||
{
|
||||
WORD_LIST *result;
|
||||
WORD_DESC *wd;
|
||||
|
||||
if (s == 0 || *s == '\0')
|
||||
return ((WORD_LIST *)NULL);
|
||||
wd = make_word (s);
|
||||
wd->flags |= W_NOGLOB|W_NOSPLIT|W_QUOTED; /* no word splitting or globbing */
|
||||
result = make_word_list (wd, (WORD_LIST *)NULL);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Note that this function calls dispose_words on EXPRS, since it doesn't
|
||||
use the word list directly. We free it here rather than at the caller
|
||||
because no other function in this file requires that the caller free
|
||||
any arguments. */
|
||||
COMMAND *
|
||||
make_arith_for_command (exprs, action, lineno)
|
||||
WORD_LIST *exprs;
|
||||
COMMAND *action;
|
||||
int lineno;
|
||||
{
|
||||
#if defined (ARITH_FOR_COMMAND)
|
||||
ARITH_FOR_COM *temp;
|
||||
WORD_LIST *init, *test, *step;
|
||||
char *s, *t, *start;
|
||||
int nsemi;
|
||||
|
||||
init = test = step = (WORD_LIST *)NULL;
|
||||
/* Parse the string into the three component sub-expressions. */
|
||||
start = t = s = exprs->word->word;
|
||||
for (nsemi = 0; ;)
|
||||
{
|
||||
/* skip whitespace at the start of each sub-expression. */
|
||||
while (whitespace (*s))
|
||||
s++;
|
||||
start = s;
|
||||
/* skip to the semicolon or EOS */
|
||||
while (*s && *s != ';')
|
||||
s++;
|
||||
|
||||
t = (s > start) ? substring (start, 0, s - start) : (char *)NULL;
|
||||
|
||||
nsemi++;
|
||||
switch (nsemi)
|
||||
{
|
||||
case 1:
|
||||
init = make_arith_for_expr (t);
|
||||
break;
|
||||
case 2:
|
||||
test = make_arith_for_expr (t);
|
||||
break;
|
||||
case 3:
|
||||
step = make_arith_for_expr (t);
|
||||
break;
|
||||
}
|
||||
|
||||
FREE (t);
|
||||
if (*s == '\0')
|
||||
break;
|
||||
s++; /* skip over semicolon */
|
||||
}
|
||||
|
||||
if (nsemi != 3)
|
||||
{
|
||||
if (nsemi < 3)
|
||||
parser_error (lineno, _("syntax error: arithmetic expression required"));
|
||||
else
|
||||
parser_error (lineno, _("syntax error: `;' unexpected"));
|
||||
parser_error (lineno, _("syntax error: `((%s))'"), exprs->word->word);
|
||||
last_command_exit_value = 2;
|
||||
return ((COMMAND *)NULL);
|
||||
}
|
||||
|
||||
temp = (ARITH_FOR_COM *)xmalloc (sizeof (ARITH_FOR_COM));
|
||||
temp->flags = 0;
|
||||
temp->line = lineno;
|
||||
temp->init = init ? init : make_arith_for_expr ("1");
|
||||
temp->test = test ? test : make_arith_for_expr ("1");
|
||||
temp->step = step ? step : make_arith_for_expr ("1");
|
||||
temp->action = action;
|
||||
|
||||
dispose_words (exprs);
|
||||
return (make_command (cm_arith_for, (SIMPLE_COM *)temp));
|
||||
#else
|
||||
dispose_words (exprs);
|
||||
last_command_exit_value = 2;
|
||||
return ((COMMAND *)NULL);
|
||||
#endif /* ARITH_FOR_COMMAND */
|
||||
}
|
||||
|
||||
COMMAND *
|
||||
make_group_command (command)
|
||||
COMMAND *command;
|
||||
{
|
||||
GROUP_COM *temp;
|
||||
|
||||
temp = (GROUP_COM *)xmalloc (sizeof (GROUP_COM));
|
||||
temp->command = command;
|
||||
return (make_command (cm_group, (SIMPLE_COM *)temp));
|
||||
}
|
||||
|
||||
COMMAND *
|
||||
make_case_command (word, clauses, lineno)
|
||||
WORD_DESC *word;
|
||||
PATTERN_LIST *clauses;
|
||||
int lineno;
|
||||
{
|
||||
CASE_COM *temp;
|
||||
|
||||
temp = (CASE_COM *)xmalloc (sizeof (CASE_COM));
|
||||
temp->flags = 0;
|
||||
temp->line = lineno;
|
||||
temp->word = word;
|
||||
temp->clauses = REVERSE_LIST (clauses, PATTERN_LIST *);
|
||||
return (make_command (cm_case, (SIMPLE_COM *)temp));
|
||||
}
|
||||
|
||||
PATTERN_LIST *
|
||||
make_pattern_list (patterns, action)
|
||||
WORD_LIST *patterns;
|
||||
COMMAND *action;
|
||||
{
|
||||
PATTERN_LIST *temp;
|
||||
|
||||
temp = (PATTERN_LIST *)xmalloc (sizeof (PATTERN_LIST));
|
||||
temp->patterns = REVERSE_LIST (patterns, WORD_LIST *);
|
||||
temp->action = action;
|
||||
temp->next = NULL;
|
||||
return (temp);
|
||||
}
|
||||
|
||||
COMMAND *
|
||||
make_if_command (test, true_case, false_case)
|
||||
COMMAND *test, *true_case, *false_case;
|
||||
{
|
||||
IF_COM *temp;
|
||||
|
||||
temp = (IF_COM *)xmalloc (sizeof (IF_COM));
|
||||
temp->flags = 0;
|
||||
temp->test = test;
|
||||
temp->true_case = true_case;
|
||||
temp->false_case = false_case;
|
||||
return (make_command (cm_if, (SIMPLE_COM *)temp));
|
||||
}
|
||||
|
||||
static COMMAND *
|
||||
make_until_or_while (which, test, action)
|
||||
enum command_type which;
|
||||
COMMAND *test, *action;
|
||||
{
|
||||
WHILE_COM *temp;
|
||||
|
||||
temp = (WHILE_COM *)xmalloc (sizeof (WHILE_COM));
|
||||
temp->flags = 0;
|
||||
temp->test = test;
|
||||
temp->action = action;
|
||||
return (make_command (which, (SIMPLE_COM *)temp));
|
||||
}
|
||||
|
||||
COMMAND *
|
||||
make_while_command (test, action)
|
||||
COMMAND *test, *action;
|
||||
{
|
||||
return (make_until_or_while (cm_while, test, action));
|
||||
}
|
||||
|
||||
COMMAND *
|
||||
make_until_command (test, action)
|
||||
COMMAND *test, *action;
|
||||
{
|
||||
return (make_until_or_while (cm_until, test, action));
|
||||
}
|
||||
|
||||
COMMAND *
|
||||
make_arith_command (exp)
|
||||
WORD_LIST *exp;
|
||||
{
|
||||
#if defined (DPAREN_ARITHMETIC)
|
||||
COMMAND *command;
|
||||
ARITH_COM *temp;
|
||||
|
||||
command = (COMMAND *)xmalloc (sizeof (COMMAND));
|
||||
command->value.Arith = temp = (ARITH_COM *)xmalloc (sizeof (ARITH_COM));
|
||||
|
||||
temp->flags = 0;
|
||||
temp->line = line_number;
|
||||
temp->exp = exp;
|
||||
|
||||
command->type = cm_arith;
|
||||
command->redirects = (REDIRECT *)NULL;
|
||||
command->flags = 0;
|
||||
|
||||
return (command);
|
||||
#else
|
||||
last_command_exit_value = 2;
|
||||
return ((COMMAND *)NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined (COND_COMMAND)
|
||||
struct cond_com *
|
||||
make_cond_node (type, op, left, right)
|
||||
int type;
|
||||
WORD_DESC *op;
|
||||
struct cond_com *left, *right;
|
||||
{
|
||||
COND_COM *temp;
|
||||
|
||||
temp = (COND_COM *)xmalloc (sizeof (COND_COM));
|
||||
temp->flags = 0;
|
||||
temp->line = line_number;
|
||||
temp->type = type;
|
||||
temp->op = op;
|
||||
temp->left = left;
|
||||
temp->right = right;
|
||||
|
||||
return (temp);
|
||||
}
|
||||
#endif
|
||||
|
||||
COMMAND *
|
||||
make_cond_command (cond_node)
|
||||
COND_COM *cond_node;
|
||||
{
|
||||
#if defined (COND_COMMAND)
|
||||
COMMAND *command;
|
||||
|
||||
command = (COMMAND *)xmalloc (sizeof (COMMAND));
|
||||
command->value.Cond = cond_node;
|
||||
|
||||
command->type = cm_cond;
|
||||
command->redirects = (REDIRECT *)NULL;
|
||||
command->flags = 0;
|
||||
command->line = cond_node ? cond_node->line : 0;
|
||||
|
||||
return (command);
|
||||
#else
|
||||
last_command_exit_value = 2;
|
||||
return ((COMMAND *)NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
COMMAND *
|
||||
make_bare_simple_command ()
|
||||
{
|
||||
COMMAND *command;
|
||||
SIMPLE_COM *temp;
|
||||
|
||||
command = (COMMAND *)xmalloc (sizeof (COMMAND));
|
||||
command->value.Simple = temp = (SIMPLE_COM *)xmalloc (sizeof (SIMPLE_COM));
|
||||
|
||||
temp->flags = 0;
|
||||
temp->line = line_number;
|
||||
temp->words = (WORD_LIST *)NULL;
|
||||
temp->redirects = (REDIRECT *)NULL;
|
||||
|
||||
command->type = cm_simple;
|
||||
command->redirects = (REDIRECT *)NULL;
|
||||
command->flags = 0;
|
||||
|
||||
return (command);
|
||||
}
|
||||
|
||||
/* Return a command which is the connection of the word or redirection
|
||||
in ELEMENT, and the command * or NULL in COMMAND. */
|
||||
COMMAND *
|
||||
make_simple_command (element, command)
|
||||
ELEMENT element;
|
||||
COMMAND *command;
|
||||
{
|
||||
/* If we are starting from scratch, then make the initial command
|
||||
structure. Also note that we have to fill in all the slots, since
|
||||
malloc doesn't return zeroed space. */
|
||||
if (!command)
|
||||
command = make_bare_simple_command ();
|
||||
|
||||
if (element.word)
|
||||
command->value.Simple->words = make_word_list (element.word, command->value.Simple->words);
|
||||
else if (element.redirect)
|
||||
{
|
||||
REDIRECT *r = element.redirect;
|
||||
/* Due to the way <> is implemented, there may be more than a single
|
||||
redirection in element.redirect. We just follow the chain as far
|
||||
as it goes, and hook onto the end. */
|
||||
while (r->next)
|
||||
r = r->next;
|
||||
r->next = command->value.Simple->redirects;
|
||||
command->value.Simple->redirects = element.redirect;
|
||||
}
|
||||
return (command);
|
||||
}
|
||||
|
||||
/* Because we are Bourne compatible, we read the input for this
|
||||
<< or <<- redirection now, from wherever input is coming from.
|
||||
We store the input read into a WORD_DESC. Replace the text of
|
||||
the redirectee.word with the new input text. If <<- is on,
|
||||
then remove leading TABS from each line. */
|
||||
void
|
||||
make_here_document (temp)
|
||||
REDIRECT *temp;
|
||||
{
|
||||
int kill_leading, redir_len;
|
||||
char *redir_word, *document, *full_line;
|
||||
int document_index, document_size, delim_unquoted;
|
||||
|
||||
if (temp->instruction != r_deblank_reading_until &&
|
||||
temp->instruction != r_reading_until)
|
||||
{
|
||||
internal_error (_("make_here_document: bad instruction type %d"), temp->instruction);
|
||||
return;
|
||||
}
|
||||
|
||||
kill_leading = temp->instruction == r_deblank_reading_until;
|
||||
|
||||
document = (char *)NULL;
|
||||
document_index = document_size = 0;
|
||||
|
||||
/* Quote removal is the only expansion performed on the delimiter
|
||||
for here documents, making it an extremely special case. */
|
||||
redir_word = string_quote_removal (temp->redirectee.filename->word, 0);
|
||||
|
||||
/* redirection_expand will return NULL if the expansion results in
|
||||
multiple words or no words. Check for that here, and just abort
|
||||
this here document if it does. */
|
||||
if (redir_word)
|
||||
redir_len = strlen (redir_word);
|
||||
else
|
||||
{
|
||||
temp->here_doc_eof = (char *)xmalloc (1);
|
||||
temp->here_doc_eof[0] = '\0';
|
||||
goto document_done;
|
||||
}
|
||||
|
||||
free (temp->redirectee.filename->word);
|
||||
temp->here_doc_eof = redir_word;
|
||||
|
||||
/* Read lines from wherever lines are coming from.
|
||||
For each line read, if kill_leading, then kill the
|
||||
leading tab characters.
|
||||
If the line matches redir_word exactly, then we have
|
||||
manufactured the document. Otherwise, add the line to the
|
||||
list of lines in the document. */
|
||||
|
||||
/* If the here-document delimiter was quoted, the lines should
|
||||
be read verbatim from the input. If it was not quoted, we
|
||||
need to perform backslash-quoted newline removal. */
|
||||
delim_unquoted = (temp->redirectee.filename->flags & W_QUOTED) == 0;
|
||||
while (full_line = read_secondary_line (delim_unquoted))
|
||||
{
|
||||
register char *line;
|
||||
int len;
|
||||
|
||||
line = full_line;
|
||||
line_number++;
|
||||
|
||||
if (kill_leading && *line)
|
||||
{
|
||||
/* Hack: To be compatible with some Bourne shells, we
|
||||
check the word before stripping the whitespace. This
|
||||
is a hack, though. */
|
||||
if (STREQN (line, redir_word, redir_len) && line[redir_len] == '\n')
|
||||
goto document_done;
|
||||
|
||||
while (*line == '\t')
|
||||
line++;
|
||||
}
|
||||
|
||||
if (*line == 0)
|
||||
continue;
|
||||
|
||||
if (STREQN (line, redir_word, redir_len) && line[redir_len] == '\n')
|
||||
goto document_done;
|
||||
|
||||
len = strlen (line);
|
||||
if (len + document_index >= document_size)
|
||||
{
|
||||
document_size = document_size ? 2 * (document_size + len) : len + 2;
|
||||
document = (char *)xrealloc (document, document_size);
|
||||
}
|
||||
|
||||
/* len is guaranteed to be > 0 because of the check for line
|
||||
being an empty string before the call to strlen. */
|
||||
FASTCOPY (line, document + document_index, len);
|
||||
document_index += len;
|
||||
}
|
||||
|
||||
document_done:
|
||||
if (document)
|
||||
document[document_index] = '\0';
|
||||
else
|
||||
{
|
||||
document = (char *)xmalloc (1);
|
||||
document[0] = '\0';
|
||||
}
|
||||
temp->redirectee.filename->word = document;
|
||||
}
|
||||
|
||||
/* Generate a REDIRECT from SOURCE, DEST, and INSTRUCTION.
|
||||
INSTRUCTION is the instruction type, SOURCE is a file descriptor,
|
||||
and DEST is a file descriptor or a WORD_DESC *. */
|
||||
REDIRECT *
|
||||
make_redirection (source, instruction, dest_and_filename)
|
||||
int source;
|
||||
enum r_instruction instruction;
|
||||
REDIRECTEE dest_and_filename;
|
||||
{
|
||||
REDIRECT *temp;
|
||||
WORD_DESC *w;
|
||||
int wlen;
|
||||
intmax_t lfd;
|
||||
|
||||
temp = (REDIRECT *)xmalloc (sizeof (REDIRECT));
|
||||
|
||||
/* First do the common cases. */
|
||||
temp->redirector = source;
|
||||
temp->redirectee = dest_and_filename;
|
||||
temp->instruction = instruction;
|
||||
temp->flags = 0;
|
||||
temp->next = (REDIRECT *)NULL;
|
||||
|
||||
switch (instruction)
|
||||
{
|
||||
|
||||
case r_output_direction: /* >foo */
|
||||
case r_output_force: /* >| foo */
|
||||
case r_err_and_out: /* command &>filename */
|
||||
temp->flags = O_TRUNC | O_WRONLY | O_CREAT;
|
||||
break;
|
||||
|
||||
case r_appending_to: /* >>foo */
|
||||
temp->flags = O_APPEND | O_WRONLY | O_CREAT;
|
||||
break;
|
||||
|
||||
case r_input_direction: /* <foo */
|
||||
case r_inputa_direction: /* foo & makes this. */
|
||||
temp->flags = O_RDONLY;
|
||||
break;
|
||||
|
||||
case r_input_output: /* <>foo */
|
||||
temp->flags = O_RDWR | O_CREAT;
|
||||
break;
|
||||
|
||||
case r_deblank_reading_until: /* <<-foo */
|
||||
case r_reading_until: /* << foo */
|
||||
case r_reading_string: /* <<< foo */
|
||||
case r_close_this: /* <&- */
|
||||
case r_duplicating_input: /* 1<&2 */
|
||||
case r_duplicating_output: /* 1>&2 */
|
||||
break;
|
||||
|
||||
/* the parser doesn't pass these. */
|
||||
case r_move_input: /* 1<&2- */
|
||||
case r_move_output: /* 1>&2- */
|
||||
case r_move_input_word: /* 1<&$foo- */
|
||||
case r_move_output_word: /* 1>&$foo- */
|
||||
break;
|
||||
|
||||
/* The way the lexer works we have to do this here. */
|
||||
case r_duplicating_input_word: /* 1<&$foo */
|
||||
case r_duplicating_output_word: /* 1>&$foo */
|
||||
w = dest_and_filename.filename;
|
||||
wlen = strlen (w->word) - 1;
|
||||
if (w->word[wlen] == '-') /* Yuck */
|
||||
{
|
||||
w->word[wlen] = '\0';
|
||||
if (all_digits (w->word) && legal_number (w->word, &lfd) && lfd == (int)lfd)
|
||||
{
|
||||
dispose_word (w);
|
||||
temp->instruction = (instruction == r_duplicating_input_word) ? r_move_input : r_move_output;
|
||||
temp->redirectee.dest = lfd;
|
||||
}
|
||||
else
|
||||
temp->instruction = (instruction == r_duplicating_input_word) ? r_move_input_word : r_move_output_word;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
programming_error (_("make_redirection: redirection instruction `%d' out of range"), instruction);
|
||||
abort ();
|
||||
break;
|
||||
}
|
||||
return (temp);
|
||||
}
|
||||
|
||||
COMMAND *
|
||||
make_function_def (name, command, lineno, lstart)
|
||||
WORD_DESC *name;
|
||||
COMMAND *command;
|
||||
int lineno, lstart;
|
||||
{
|
||||
FUNCTION_DEF *temp;
|
||||
#if defined (ARRAY_VARS)
|
||||
SHELL_VAR *bash_source_v;
|
||||
ARRAY *bash_source_a;
|
||||
char *t;
|
||||
#endif
|
||||
|
||||
temp = (FUNCTION_DEF *)xmalloc (sizeof (FUNCTION_DEF));
|
||||
temp->command = command;
|
||||
temp->name = name;
|
||||
temp->line = lineno;
|
||||
temp->flags = 0;
|
||||
command->line = lstart;
|
||||
|
||||
/* Information used primarily for debugging. */
|
||||
temp->source_file = 0;
|
||||
#if defined (ARRAY_VARS)
|
||||
GET_ARRAY_FROM_VAR ("BASH_SOURCE", bash_source_v, bash_source_a);
|
||||
if (bash_source_a && array_num_elements (bash_source_a) > 0)
|
||||
temp->source_file = array_reference (bash_source_a, 0);
|
||||
#endif
|
||||
bind_function_def (name->word, temp);
|
||||
|
||||
temp->source_file = 0;
|
||||
return (make_command (cm_function_def, (SIMPLE_COM *)temp));
|
||||
}
|
||||
|
||||
COMMAND *
|
||||
make_subshell_command (command)
|
||||
COMMAND *command;
|
||||
{
|
||||
SUBSHELL_COM *temp;
|
||||
|
||||
temp = (SUBSHELL_COM *)xmalloc (sizeof (SUBSHELL_COM));
|
||||
temp->command = command;
|
||||
temp->flags = CMD_WANT_SUBSHELL;
|
||||
return (make_command (cm_subshell, (SIMPLE_COM *)temp));
|
||||
}
|
||||
|
||||
/* Reverse the word list and redirection list in the simple command
|
||||
has just been parsed. It seems simpler to do this here the one
|
||||
time then by any other method that I can think of. */
|
||||
COMMAND *
|
||||
clean_simple_command (command)
|
||||
COMMAND *command;
|
||||
{
|
||||
if (command->type != cm_simple)
|
||||
command_error ("clean_simple_command", CMDERR_BADTYPE, command->type, 0);
|
||||
else
|
||||
{
|
||||
command->value.Simple->words =
|
||||
REVERSE_LIST (command->value.Simple->words, WORD_LIST *);
|
||||
command->value.Simple->redirects =
|
||||
REVERSE_LIST (command->value.Simple->redirects, REDIRECT *);
|
||||
}
|
||||
|
||||
return (command);
|
||||
}
|
||||
|
||||
/* The Yacc grammar productions have a problem, in that they take a
|
||||
list followed by an ampersand (`&') and do a simple command connection,
|
||||
making the entire list effectively asynchronous, instead of just
|
||||
the last command. This means that when the list is executed, all
|
||||
the commands have stdin set to /dev/null when job control is not
|
||||
active, instead of just the last. This is wrong, and needs fixing
|
||||
up. This function takes the `&' and applies it to the last command
|
||||
in the list. This is done only for lists connected by `;'; it makes
|
||||
`;' bind `tighter' than `&'. */
|
||||
COMMAND *
|
||||
connect_async_list (command, command2, connector)
|
||||
COMMAND *command, *command2;
|
||||
int connector;
|
||||
{
|
||||
COMMAND *t, *t1, *t2;
|
||||
|
||||
t1 = command;
|
||||
t = command->value.Connection->second;
|
||||
|
||||
if (!t || (command->flags & CMD_WANT_SUBSHELL) ||
|
||||
command->value.Connection->connector != ';')
|
||||
{
|
||||
t = command_connect (command, command2, connector);
|
||||
return t;
|
||||
}
|
||||
|
||||
/* This is just defensive programming. The Yacc precedence rules
|
||||
will generally hand this function a command where t points directly
|
||||
to the command we want (e.g. given a ; b ; c ; d &, t1 will point
|
||||
to the `a ; b ; c' list and t will be the `d'). We only want to do
|
||||
this if the list is not being executed as a unit in the background
|
||||
with `( ... )', so we have to check for CMD_WANT_SUBSHELL. That's
|
||||
the only way to tell. */
|
||||
while (((t->flags & CMD_WANT_SUBSHELL) == 0) && t->type == cm_connection &&
|
||||
t->value.Connection->connector == ';')
|
||||
{
|
||||
t1 = t;
|
||||
t = t->value.Connection->second;
|
||||
}
|
||||
/* Now we have t pointing to the last command in the list, and
|
||||
t1->value.Connection->second == t. */
|
||||
t2 = command_connect (t, command2, connector);
|
||||
t1->value.Connection->second = t2;
|
||||
return command;
|
||||
}
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
/* make_cmd.h -- Declarations of functions found in make_cmd.c */
|
||||
|
||||
/* Copyright (C) 1993 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1993-2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/* make_cmd.h -- Declarations of functions found in make_cmd.c */
|
||||
|
||||
/* Copyright (C) 1993 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. */
|
||||
|
||||
#if !defined (_MAKE_CMD_H_)
|
||||
#define _MAKE_CMD_H_
|
||||
|
||||
#include "stdc.h"
|
||||
|
||||
extern void cmd_init __P((void));
|
||||
|
||||
extern WORD_DESC *alloc_word_desc __P((void));
|
||||
extern WORD_DESC *make_bare_word __P((const char *));
|
||||
extern WORD_DESC *make_word_flags __P((WORD_DESC *, const char *));
|
||||
extern WORD_DESC *make_word __P((const char *));
|
||||
extern WORD_DESC *make_word_from_token __P((int));
|
||||
|
||||
extern WORD_LIST *make_word_list __P((WORD_DESC *, WORD_LIST *));
|
||||
|
||||
#define add_string_to_list(s, l) make_word_list (make_word(s), (l))
|
||||
|
||||
extern COMMAND *make_command __P((enum command_type, SIMPLE_COM *));
|
||||
extern COMMAND *command_connect __P((COMMAND *, COMMAND *, int));
|
||||
extern COMMAND *make_for_command __P((WORD_DESC *, WORD_LIST *, COMMAND *, int));
|
||||
extern COMMAND *make_group_command __P((COMMAND *));
|
||||
extern COMMAND *make_case_command __P((WORD_DESC *, PATTERN_LIST *, int));
|
||||
extern PATTERN_LIST *make_pattern_list __P((WORD_LIST *, COMMAND *));
|
||||
extern COMMAND *make_if_command __P((COMMAND *, COMMAND *, COMMAND *));
|
||||
extern COMMAND *make_while_command __P((COMMAND *, COMMAND *));
|
||||
extern COMMAND *make_until_command __P((COMMAND *, COMMAND *));
|
||||
extern COMMAND *make_bare_simple_command __P((void));
|
||||
extern COMMAND *make_simple_command __P((ELEMENT, COMMAND *));
|
||||
extern void make_here_document __P((REDIRECT *));
|
||||
extern REDIRECT *make_redirection __P((int, enum r_instruction, REDIRECTEE));
|
||||
extern COMMAND *make_function_def __P((WORD_DESC *, COMMAND *, int, int));
|
||||
extern COMMAND *clean_simple_command __P((COMMAND *));
|
||||
|
||||
extern COMMAND *make_arith_command __P((WORD_LIST *));
|
||||
|
||||
extern COMMAND *make_select_command __P((WORD_DESC *, WORD_LIST *, COMMAND *, int));
|
||||
|
||||
#if defined (COND_COMMAND)
|
||||
extern COND_COM *make_cond_node __P((int, WORD_DESC *, COND_COM *, COND_COM *));
|
||||
extern COMMAND *make_cond_command __P((COND_COM *));
|
||||
#endif
|
||||
|
||||
extern COMMAND *make_arith_for_command __P((WORD_LIST *, COMMAND *, int));
|
||||
|
||||
extern COMMAND *make_subshell_command __P((COMMAND *));
|
||||
|
||||
extern COMMAND *connect_async_list __P((COMMAND *, COMMAND *, int));
|
||||
|
||||
#endif /* !_MAKE_CMD_H */
|
||||
@@ -1,6 +1,6 @@
|
||||
/* Yacc grammar for bash. */
|
||||
|
||||
/* Copyright (C) 1989-2004 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1989-2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
@@ -2066,16 +2066,6 @@ shell_getc (remove_quoted_newline)
|
||||
if (uc)
|
||||
shell_input_line_index++;
|
||||
|
||||
#if 0
|
||||
if MBTEST(uc == '\\' && remove_quoted_newline && shell_input_line[shell_input_line_index] == '\n')
|
||||
{
|
||||
if (SHOULD_PROMPT ())
|
||||
prompt_again ();
|
||||
line_number++;
|
||||
goto restart_read;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined (ALIAS) || defined (DPAREN_ARITHMETIC)
|
||||
/* If UC is NULL, we have reached the end of the current input string. If
|
||||
pushed_string_list is non-empty, it's time to pop to the previous string
|
||||
@@ -2091,7 +2081,6 @@ shell_getc (remove_quoted_newline)
|
||||
}
|
||||
#endif /* ALIAS || DPAREN_ARITHMETIC */
|
||||
|
||||
#if 1
|
||||
if MBTEST(uc == '\\' && remove_quoted_newline && shell_input_line[shell_input_line_index] == '\n')
|
||||
{
|
||||
if (SHOULD_PROMPT ())
|
||||
@@ -2099,7 +2088,6 @@ shell_getc (remove_quoted_newline)
|
||||
line_number++;
|
||||
goto restart_read;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!uc && shell_input_line_terminator == EOF)
|
||||
return ((shell_input_line_index != 0) ? '\n' : EOF);
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
/* pcomplete.c - functions to generate lists of matches for programmable
|
||||
completion. */
|
||||
|
||||
/* Copyright (C) 1999-2004 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1999-2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
+4
-2
@@ -513,6 +513,7 @@ it_init_joblist (itp, jstate)
|
||||
register int i;
|
||||
register PROCESS *p;
|
||||
char *s, *t;
|
||||
JOB *j;
|
||||
JOB_STATE ws; /* wanted state */
|
||||
|
||||
if (jstate == 0)
|
||||
@@ -523,9 +524,10 @@ it_init_joblist (itp, jstate)
|
||||
sl = strlist_create (js.j_jobslots);
|
||||
for (i = js.j_jobslots - 1; i >= 0; i--)
|
||||
{
|
||||
if (jobs[i] == 0)
|
||||
j = get_job_by_jid (i);
|
||||
if (j == 0)
|
||||
continue;
|
||||
p = jobs[i]->pipe;
|
||||
p = j->pipe;
|
||||
if (jstate == -1 || JOBSTATE(i) == ws)
|
||||
{
|
||||
s = savestring (p->command);
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
/* print_command -- A way to make readable commands from a command tree. */
|
||||
|
||||
/* Copyright (C) 1989-2004 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1989-2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
+1307
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,10 @@
|
||||
/* subst.c -- The part of the shell that does parameter, command, and
|
||||
globbing substitutions. */
|
||||
/* subst.c -- The part of the shell that does parameter, command, arithmetic,
|
||||
and globbing substitutions. */
|
||||
|
||||
/* ``Have a little faith, there's magic in the night. You ain't a
|
||||
beauty, but, hey, you're alright.'' */
|
||||
|
||||
/* Copyright (C) 1987-2004 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
@@ -6931,7 +6931,7 @@ add_twochars:
|
||||
cases: a quoted null character as above and when
|
||||
CTLNUL is contained in the (non-null) expansion
|
||||
of some variable. We use the had_quoted_null flag to
|
||||
pass the value through this function to its return value. */
|
||||
pass the value through this function to its caller. */
|
||||
if ((tflag & W_HASQUOTEDNULL) && QUOTED_NULL (temp) == 0)
|
||||
remove_quoted_nulls (temp); /* XXX */
|
||||
}
|
||||
|
||||
+8
-4
@@ -78,10 +78,14 @@ sunos4*)
|
||||
sunos5*-*gcc*|solaris2*-*gcc*)
|
||||
SHOBJ_CFLAGS=-fpic
|
||||
SHOBJ_LD='${CC}'
|
||||
# This line works for the Solaris linker in /usr/ccs/bin/ld
|
||||
SHOBJ_LDFLAGS='-shared -Wl,-i -Wl,-h,$@'
|
||||
# This line works for the GNU ld
|
||||
# SHOBJ_LDFLAGS='-shared -Wl,-h,$@'
|
||||
ld_used=`gcc -print-prog-name=ld`
|
||||
if ${ld_used} -V 2>&1 | grep GNU >/dev/null 2>&1; then
|
||||
# This line works for the GNU ld
|
||||
SHOBJ_LDFLAGS='-shared -Wl,-h,$@'
|
||||
else
|
||||
# This line works for the Solaris linker in /usr/ccs/bin/ld
|
||||
SHOBJ_LDFLAGS='-shared -Wl,-i -Wl,-h,$@'
|
||||
fi
|
||||
|
||||
# SHLIB_XLDFLAGS='-R $(libdir)'
|
||||
SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)'
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
BUILD_DIR=/usr/local/build/bash/bash-current
|
||||
BUILD_DIR=/usr/local/build/chet/bash/bash-current
|
||||
THIS_SH=$BUILD_DIR/bash
|
||||
PATH=$PATH:$BUILD_DIR
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* trap.c -- Not the trap command, but useful functions for manipulating
|
||||
those objects. The trap command is in builtins/trap.def. */
|
||||
|
||||
/* Copyright (C) 1987-2003 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
@@ -875,9 +875,12 @@ reset_or_restore_signal_handlers (reset)
|
||||
/* Take care of the exit trap first */
|
||||
if (sigmodes[EXIT_TRAP] & SIG_TRAPPED)
|
||||
{
|
||||
free_trap_command (EXIT_TRAP);
|
||||
trap_list[EXIT_TRAP] = (char *)NULL;
|
||||
sigmodes[EXIT_TRAP] &= ~SIG_TRAPPED;
|
||||
if (reset != reset_signal)
|
||||
{
|
||||
free_trap_command (EXIT_TRAP);
|
||||
trap_list[EXIT_TRAP] = (char *)NULL;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 1; i < NSIG; i++)
|
||||
|
||||
+5
-1
@@ -1,6 +1,6 @@
|
||||
/* variables.c -- Functions for hacking shell variables. */
|
||||
|
||||
/* Copyright (C) 1987-2004 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -350,7 +350,11 @@ initialize_shell_variables (env, privmode)
|
||||
set_pwd ();
|
||||
|
||||
/* Set up initial value of $_ */
|
||||
#if 0
|
||||
temp_var = bind_variable ("_", dollar_vars[0], 0);
|
||||
#else
|
||||
temp_var = set_if_not ("_", dollar_vars[0]);
|
||||
#endif
|
||||
|
||||
/* Remember this pid. */
|
||||
dollar_dollar_pid = getpid ();
|
||||
|
||||
+5
-2
@@ -1,6 +1,6 @@
|
||||
/* variables.c -- Functions for hacking shell variables. */
|
||||
|
||||
/* Copyright (C) 1987-2004 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -350,7 +350,11 @@ initialize_shell_variables (env, privmode)
|
||||
set_pwd ();
|
||||
|
||||
/* Set up initial value of $_ */
|
||||
#if 1
|
||||
temp_var = bind_variable ("_", dollar_vars[0], 0);
|
||||
#else
|
||||
temp_var = set_if_not ("_", dollar_vars[0]);
|
||||
#endif
|
||||
|
||||
/* Remember this pid. */
|
||||
dollar_dollar_pid = getpid ();
|
||||
@@ -1149,7 +1153,6 @@ get_random_number ()
|
||||
/* Reset for command and process substitution. */
|
||||
if (subshell_environment && seeded_subshell == 0)
|
||||
{
|
||||
itrace("seeding random number gen in subshell");
|
||||
sbrand (rseed + getpid() + NOW);
|
||||
seeded_subshell = 1;
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
/* variables.h -- data structures for shell variables. */
|
||||
|
||||
/* Copyright (C) 1987-2004 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
@@ -330,6 +330,7 @@ extern int get_random_number __P((void));
|
||||
extern void sv_ifs __P((char *));
|
||||
extern void sv_path __P((char *));
|
||||
extern void sv_mail __P((char *));
|
||||
extern void sv_comp_wordbreaks __P((char *));
|
||||
extern void sv_globignore __P((char *));
|
||||
extern void sv_ignoreeof __P((char *));
|
||||
extern void sv_strict_posix __P((char *));
|
||||
|
||||
Reference in New Issue
Block a user