mirror of https://github.com/n-hys/bash.git
190 lines
4.2 KiB
Modula-2
190 lines
4.2 KiB
Modula-2
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-2020 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 3 of the License, 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. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
$PRODUCES fg_bg.c
|
|
|
|
$BUILTIN fg
|
|
$FUNCTION fg_builtin
|
|
$DEPENDS_ON JOB_CONTROL
|
|
$SHORT_DOC fg [job_spec]
|
|
Move job to the foreground.
|
|
|
|
Place the job identified by JOB_SPEC in the foreground, making it the
|
|
current job. If JOB_SPEC is not present, the shell's notion of the
|
|
current job is used.
|
|
|
|
Exit Status:
|
|
Status of command placed in foreground, or failure if an error occurs.
|
|
$END
|
|
|
|
#include <config.h>
|
|
|
|
#include "../bashtypes.h"
|
|
#include <signal.h>
|
|
|
|
#if defined (HAVE_UNISTD_H)
|
|
# include <unistd.h>
|
|
#endif
|
|
|
|
#include "../bashintl.h"
|
|
|
|
#include "../shell.h"
|
|
#include "../execute_cmd.h"
|
|
#include "../jobs.h"
|
|
#include "common.h"
|
|
#include "bashgetopt.h"
|
|
|
|
#if defined (JOB_CONTROL)
|
|
static int fg_bg PARAMS((WORD_LIST *, int));
|
|
|
|
/* How to bring a job into the foreground. */
|
|
int
|
|
fg_builtin (list)
|
|
WORD_LIST *list;
|
|
{
|
|
int fg_bit;
|
|
register WORD_LIST *t;
|
|
|
|
CHECK_HELPOPT (list);
|
|
|
|
if (job_control == 0)
|
|
{
|
|
sh_nojobs ((char *)NULL);
|
|
return (EXECUTION_FAILURE);
|
|
}
|
|
|
|
if (no_options (list))
|
|
return (EX_USAGE);
|
|
list = loptend;
|
|
|
|
/* If the last arg on the line is '&', then start this job in the
|
|
background. Else, fg the job. */
|
|
for (t = list; t && t->next; t = t->next)
|
|
;
|
|
fg_bit = (t && t->word->word[0] == '&' && t->word->word[1] == '\0') == 0;
|
|
|
|
return (fg_bg (list, fg_bit));
|
|
}
|
|
#endif /* JOB_CONTROL */
|
|
|
|
$BUILTIN bg
|
|
$FUNCTION bg_builtin
|
|
$DEPENDS_ON JOB_CONTROL
|
|
$SHORT_DOC bg [job_spec ...]
|
|
Move jobs to the background.
|
|
|
|
Place the jobs identified by each JOB_SPEC in the background, as if they
|
|
had been started with `&'. If JOB_SPEC is not present, the shell's notion
|
|
of the current job is used.
|
|
|
|
Exit Status:
|
|
Returns success unless job control is not enabled or an error occurs.
|
|
$END
|
|
|
|
#if defined (JOB_CONTROL)
|
|
/* How to put a job into the background. */
|
|
int
|
|
bg_builtin (list)
|
|
WORD_LIST *list;
|
|
{
|
|
int r;
|
|
|
|
CHECK_HELPOPT (list);
|
|
|
|
if (job_control == 0)
|
|
{
|
|
sh_nojobs ((char *)NULL);
|
|
return (EXECUTION_FAILURE);
|
|
}
|
|
|
|
if (no_options (list))
|
|
return (EX_USAGE);
|
|
list = loptend;
|
|
|
|
/* This relies on the fact that fg_bg() takes a WORD_LIST *, but only acts
|
|
on the first member (if any) of that list. */
|
|
r = EXECUTION_SUCCESS;
|
|
do
|
|
{
|
|
if (fg_bg (list, 0) == EXECUTION_FAILURE)
|
|
r = EXECUTION_FAILURE;
|
|
if (list)
|
|
list = list->next;
|
|
}
|
|
while (list);
|
|
|
|
return r;
|
|
}
|
|
|
|
/* How to put a job into the foreground/background. */
|
|
static int
|
|
fg_bg (list, foreground)
|
|
WORD_LIST *list;
|
|
int foreground;
|
|
{
|
|
sigset_t set, oset;
|
|
int job, status, old_async_pid;
|
|
JOB *j;
|
|
|
|
BLOCK_CHILD (set, oset);
|
|
job = get_job_spec (list);
|
|
|
|
if (INVALID_JOB (job))
|
|
{
|
|
if (job != DUP_JOB)
|
|
sh_badjob (list ? list->word->word : _("current"));
|
|
|
|
goto failure;
|
|
}
|
|
|
|
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);
|
|
goto failure;
|
|
}
|
|
|
|
if (foreground == 0)
|
|
{
|
|
old_async_pid = last_asynchronous_pid;
|
|
last_asynchronous_pid = j->pgrp; /* As per Posix.2 5.4.2 */
|
|
}
|
|
|
|
status = start_job (job, foreground);
|
|
|
|
if (status >= 0)
|
|
{
|
|
/* win: */
|
|
UNBLOCK_CHILD (oset);
|
|
return (foreground ? status : EXECUTION_SUCCESS);
|
|
}
|
|
else
|
|
{
|
|
if (foreground == 0)
|
|
last_asynchronous_pid = old_async_pid;
|
|
|
|
failure:
|
|
UNBLOCK_CHILD (oset);
|
|
return (EXECUTION_FAILURE);
|
|
}
|
|
}
|
|
#endif /* JOB_CONTROL */
|