1This file is fg_bg.def, from which is created fg_bg.c. 2It implements the builtins "bg" and "fg" in Bash. 3 4Copyright (C) 1987-2009 Free Software Foundation, Inc. 5 6This file is part of GNU Bash, the Bourne Again SHell. 7 8Bash is free software: you can redistribute it and/or modify 9it under the terms of the GNU General Public License as published by 10the Free Software Foundation, either version 3 of the License, or 11(at your option) any later version. 12 13Bash is distributed in the hope that it will be useful, 14but WITHOUT ANY WARRANTY; without even the implied warranty of 15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16GNU General Public License for more details. 17 18You should have received a copy of the GNU General Public License 19along with Bash. If not, see <http://www.gnu.org/licenses/>. 20 21$PRODUCES fg_bg.c 22 23$BUILTIN fg 24$FUNCTION fg_builtin 25$DEPENDS_ON JOB_CONTROL 26$SHORT_DOC fg [job_spec] 27Move job to the foreground. 28 29Place the job identified by JOB_SPEC in the foreground, making it the 30current job. If JOB_SPEC is not present, the shell's notion of the 31current job is used. 32 33Exit Status: 34Status of command placed in foreground, or failure if an error occurs. 35$END 36 37#include <config.h> 38 39#include "../bashtypes.h" 40#include <signal.h> 41 42#if defined (HAVE_UNISTD_H) 43# include <unistd.h> 44#endif 45 46#include "../bashintl.h" 47 48#include "../shell.h" 49#include "../jobs.h" 50#include "common.h" 51#include "bashgetopt.h" 52 53#if defined (JOB_CONTROL) 54extern char *this_command_name; 55 56static int fg_bg __P((WORD_LIST *, int)); 57 58/* How to bring a job into the foreground. */ 59int 60fg_builtin (list) 61 WORD_LIST *list; 62{ 63 int fg_bit; 64 register WORD_LIST *t; 65 66 if (job_control == 0) 67 { 68 sh_nojobs ((char *)NULL); 69 return (EXECUTION_FAILURE); 70 } 71 72 if (no_options (list)) 73 return (EX_USAGE); 74 list = loptend; 75 76 /* If the last arg on the line is '&', then start this job in the 77 background. Else, fg the job. */ 78 for (t = list; t && t->next; t = t->next) 79 ; 80 fg_bit = (t && t->word->word[0] == '&' && t->word->word[1] == '\0') == 0; 81 82 return (fg_bg (list, fg_bit)); 83} 84#endif /* JOB_CONTROL */ 85 86$BUILTIN bg 87$FUNCTION bg_builtin 88$DEPENDS_ON JOB_CONTROL 89$SHORT_DOC bg [job_spec ...] 90Move jobs to the background. 91 92Place the jobs identified by each JOB_SPEC in the background, as if they 93had been started with `&'. If JOB_SPEC is not present, the shell's notion 94of the current job is used. 95 96Exit Status: 97Returns success unless job control is not enabled or an error occurs. 98$END 99 100#if defined (JOB_CONTROL) 101/* How to put a job into the background. */ 102int 103bg_builtin (list) 104 WORD_LIST *list; 105{ 106 int r; 107 108 if (job_control == 0) 109 { 110 sh_nojobs ((char *)NULL); 111 return (EXECUTION_FAILURE); 112 } 113 114 if (no_options (list)) 115 return (EX_USAGE); 116 list = loptend; 117 118 /* This relies on the fact that fg_bg() takes a WORD_LIST *, but only acts 119 on the first member (if any) of that list. */ 120 r = EXECUTION_SUCCESS; 121 do 122 { 123 if (fg_bg (list, 0) == EXECUTION_FAILURE) 124 r = EXECUTION_FAILURE; 125 if (list) 126 list = list->next; 127 } 128 while (list); 129 130 return r; 131} 132 133/* How to put a job into the foreground/background. */ 134static int 135fg_bg (list, foreground) 136 WORD_LIST *list; 137 int foreground; 138{ 139 sigset_t set, oset; 140 int job, status, old_async_pid; 141 JOB *j; 142 143 BLOCK_CHILD (set, oset); 144 job = get_job_spec (list); 145 146 if (INVALID_JOB (job)) 147 { 148 if (job != DUP_JOB) 149 sh_badjob (list ? list->word->word : _("current")); 150 151 goto failure; 152 } 153 154 j = get_job_by_jid (job); 155 /* Or if j->pgrp == shell_pgrp. */ 156 if (IS_JOBCONTROL (job) == 0) 157 { 158 builtin_error (_("job %d started without job control"), job + 1); 159 goto failure; 160 } 161 162 if (foreground == 0) 163 { 164 old_async_pid = last_asynchronous_pid; 165 last_asynchronous_pid = j->pgrp; /* As per Posix.2 5.4.2 */ 166 } 167 168 status = start_job (job, foreground); 169 170 if (status >= 0) 171 { 172 /* win: */ 173 UNBLOCK_CHILD (oset); 174 return (foreground ? status : EXECUTION_SUCCESS); 175 } 176 else 177 { 178 if (foreground == 0) 179 last_asynchronous_pid = old_async_pid; 180 181 failure: 182 UNBLOCK_CHILD (oset); 183 return (EXECUTION_FAILURE); 184 } 185} 186#endif /* JOB_CONTROL */ 187