]>
Commit | Line | Data |
---|---|---|
726f6388 JA |
1 | /* jobs.h -- structures and stuff used by the jobs.c file. */ |
2 | ||
3 | /* Copyright (C) 1993 Free Software Foundation, Inc. | |
4 | ||
5 | This file is part of GNU Bash, the Bourne Again SHell. | |
6 | ||
7 | Bash is free software; you can redistribute it and/or modify it under | |
8 | the terms of the GNU General Public License as published by the Free | |
9 | Software Foundation; either version 2, or (at your option) any later | |
10 | version. | |
11 | ||
12 | Bash is distributed in the hope that it will be useful, but WITHOUT ANY | |
13 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 | for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License along | |
18 | with Bash; see the file COPYING. If not, write to the Free Software | |
19 | Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
20 | ||
21 | #if !defined (__JOBS_H__) | |
22 | # define __JOBS_H__ | |
23 | ||
24 | #include "quit.h" | |
25 | #include "siglist.h" | |
26 | ||
27 | #include "stdc.h" | |
28 | ||
29 | /* Defines controlling the fashion in which jobs are listed. */ | |
30 | #define JLIST_STANDARD 0 | |
31 | #define JLIST_LONG 1 | |
32 | #define JLIST_PID_ONLY 2 | |
33 | #define JLIST_CHANGED_ONLY 3 | |
34 | ||
35 | #if defined (HAVE_WAIT_H) | |
36 | # include <sys/wait.h> | |
37 | #else /* !HAVE_WAIT_H */ | |
38 | ||
39 | # include "bash_endian.h" | |
40 | ||
41 | # if !defined (_POSIX_VERSION) | |
42 | # if defined (LITTLE_ENDIAN) | |
43 | union wait | |
44 | { | |
45 | int w_status; /* used in syscall */ | |
46 | ||
47 | /* Terminated process status. */ | |
48 | struct | |
49 | { | |
50 | unsigned short | |
51 | w_Termsig : 7, /* termination signal */ | |
52 | w_Coredump : 1, /* core dump indicator */ | |
53 | w_Retcode : 8, /* exit code if w_termsig==0 */ | |
54 | w_Fill1 : 16; /* high 16 bits unused */ | |
55 | } w_T; | |
56 | ||
57 | /* Stopped process status. Returned | |
58 | only for traced children unless requested | |
59 | with the WUNTRACED option bit. */ | |
60 | struct | |
61 | { | |
62 | unsigned short | |
63 | w_Stopval : 8, /* == W_STOPPED if stopped */ | |
64 | w_Stopsig : 8, /* actually zero on XENIX */ | |
65 | w_Fill2 : 16; /* high 16 bits unused */ | |
66 | } w_S; | |
67 | }; | |
68 | ||
69 | # else /* !LITTLE_ENDIAN */ | |
70 | ||
71 | /* This is for big-endian machines like the IBM RT, HP 9000, or Sun-3 */ | |
72 | ||
73 | union wait | |
74 | { | |
75 | int w_status; /* used in syscall */ | |
76 | ||
77 | /* Terminated process status. */ | |
78 | struct | |
79 | { | |
80 | unsigned short w_Fill1 : 16; /* high 16 bits unused */ | |
81 | unsigned w_Retcode : 8; /* exit code if w_termsig==0 */ | |
82 | unsigned w_Coredump : 1; /* core dump indicator */ | |
83 | unsigned w_Termsig : 7; /* termination signal */ | |
84 | } w_T; | |
85 | ||
86 | /* Stopped process status. Returned | |
87 | only for traced children unless requested | |
88 | with the WUNTRACED option bit. */ | |
89 | struct | |
90 | { | |
91 | unsigned short w_Fill2 : 16; /* high 16 bits unused */ | |
92 | unsigned w_Stopsig : 8; /* signal that stopped us */ | |
93 | unsigned w_Stopval : 8; /* == W_STOPPED if stopped */ | |
94 | } w_S; | |
95 | }; | |
96 | ||
97 | # endif /* !LITTLE_ENDIAN */ | |
98 | ||
99 | # define w_termsig w_T.w_Termsig | |
100 | # define w_coredump w_T.w_Coredump | |
101 | # define w_retcode w_T.w_Retcode | |
102 | # define w_stopval w_S.w_Stopval | |
103 | # define w_stopsig w_S.w_Stopsig | |
104 | ||
105 | /* Note that sys/wait.h defines these for Posix systems. */ | |
106 | # define WSTOPPED 0177 | |
107 | # define WIFSTOPPED(x) (((x) . w_stopval) == WSTOPPED) | |
108 | # define WIFEXITED(x) ((! (WIFSTOPPED (x))) && (((x) . w_termsig) == 0)) | |
109 | # define WIFSIGNALED(x) ((! (WIFSTOPPED (x))) && (((x) . w_termsig) != 0)) | |
110 | # endif /* !_POSIX_VERSION */ | |
111 | #endif /* !HAVE_WAIT_H */ | |
112 | ||
113 | /* How to get the status of a job. For Posix, this is just an | |
114 | int, but for other systems we have to crack the union wait. */ | |
115 | #if !defined (_POSIX_VERSION) | |
116 | # define pid_t int | |
117 | typedef union wait WAIT; | |
118 | # define WSTATUS(t) (t.w_status) | |
119 | #else /* _POSIX_VERSION */ | |
120 | typedef int WAIT; | |
121 | # define WSTATUS(t) (t) | |
122 | #endif /* _POSIX_VERSION */ | |
123 | ||
124 | /* Make sure that parameters to wait3 are defined. */ | |
125 | #if !defined (WNOHANG) | |
126 | # define WNOHANG 1 | |
127 | # define WUNTRACED 2 | |
128 | #endif /* WNOHANG */ | |
129 | ||
130 | /* More Posix P1003.1 definitions. In the POSIX versions, the parameter is | |
131 | passed as an `int', in the non-POSIX version, as `union wait'. */ | |
132 | #if defined (_POSIX_VERSION) | |
133 | ||
134 | # if !defined (WSTOPSIG) | |
135 | # define WSTOPSIG(s) ((s) >> 8) | |
136 | # endif /* !WSTOPSIG */ | |
137 | ||
138 | # if !defined (WTERMSIG) | |
139 | # define WTERMSIG(s) ((s) & 0177) | |
140 | # endif /* !WTERMSIG */ | |
141 | ||
142 | # if !defined (WEXITSTATUS) | |
143 | # define WEXITSTATUS(s) ((s) >> 8) | |
144 | # endif /* !WEXITSTATUS */ | |
145 | ||
146 | # if !defined (WIFSTOPPED) | |
147 | # define WIFSTOPPED(s) (((s) & 0177) == 0177) | |
148 | # endif /* !WIFSTOPPED */ | |
149 | ||
150 | # if !defined (WIFEXITED) | |
151 | # define WIFEXITED(s) (((s) & 0377) == 0) | |
152 | # endif /* !WIFEXITED */ | |
153 | ||
154 | # if !defined (WIFSIGNALED) | |
155 | # define WIFSIGNALED(s) (!WIFSTOPPED(s) && !WIFEXITED(s)) | |
156 | # endif /* !WIFSIGNALED */ | |
157 | ||
158 | # if !defined (WIFCORED) | |
159 | # define WIFCORED(s) ((s) & 0200) | |
160 | # endif /* !WIFCORED */ | |
161 | ||
162 | #else /* !_POSIX_VERSION */ | |
163 | ||
164 | # if !defined (WSTOPSIG) | |
165 | # define WSTOPSIG(s) ((s).w_stopsig) | |
166 | # endif /* !WSTOPSIG */ | |
167 | ||
168 | # if !defined (WTERMSIG) | |
169 | # define WTERMSIG(s) ((s).w_termsig) | |
170 | # endif /* !WTERMSIG */ | |
171 | ||
172 | # if !defined (WEXITSTATUS) | |
173 | # define WEXITSTATUS(s) ((s).w_retcode) | |
174 | # endif /* !WEXITSTATUS */ | |
175 | ||
176 | # if !defined (WIFCORED) | |
177 | # define WIFCORED(s) ((s).w_coredump) | |
178 | # endif /* !WIFCORED */ | |
179 | ||
180 | #endif /* !_POSIX_VERSION */ | |
181 | ||
182 | /* I looked it up. For pretty_print_job (). The real answer is 24. */ | |
183 | #define LONGEST_SIGNAL_DESC 24 | |
184 | ||
185 | /* We keep an array of jobs. Each entry in the array is a linked list | |
186 | of processes that are piped together. The first process encountered is | |
187 | the group leader. */ | |
188 | ||
189 | /* Each child of the shell is remembered in a STRUCT PROCESS. A chain of | |
190 | such structures is a pipeline. The chain is circular. */ | |
191 | typedef struct process { | |
192 | struct process *next; /* Next process in the pipeline. A circular chain. */ | |
193 | pid_t pid; /* Process ID. */ | |
194 | WAIT status; /* The status of this command as returned by wait. */ | |
195 | int running; /* Non-zero if this process is running. */ | |
196 | char *command; /* The particular program that is running. */ | |
197 | } PROCESS; | |
198 | ||
199 | /* A description of a pipeline's state. */ | |
200 | typedef enum { JRUNNING, JSTOPPED, JDEAD, JMIXED } JOB_STATE; | |
201 | #define JOBSTATE(job) (jobs[(job)]->state) | |
202 | ||
203 | /* Values for the FLAGS field in the JOB struct below. */ | |
204 | #define J_FOREGROUND 0x01 /* Non-zero if this is running in the foreground. */ | |
205 | #define J_NOTIFIED 0x02 /* Non-zero if already notified about job state. */ | |
206 | #define J_JOBCONTROL 0x04 /* Non-zero if this job started under job control. */ | |
207 | ||
208 | typedef struct job { | |
209 | char *wd; /* The working directory at time of invocation. */ | |
210 | PROCESS *pipe; /* The pipeline of processes that make up this job. */ | |
211 | pid_t pgrp; /* The process ID of the process group (necessary). */ | |
212 | JOB_STATE state; /* The state that this job is in. */ | |
213 | int flags; /* Flags word: J_NOTIFIED, J_FOREGROUND, or J_JOBCONTROL. */ | |
214 | #if defined (JOB_CONTROL) | |
215 | COMMAND *deferred; /* Commands that will execute when this job is done. */ | |
216 | #endif /* JOB_CONTROL */ | |
217 | } JOB; | |
218 | ||
219 | #define NO_JOB -1 /* An impossible job array index. */ | |
220 | #define DUP_JOB -2 /* A possible return value for get_job_spec (). */ | |
221 | ||
222 | /* A value which cannot be a process ID. */ | |
223 | #define NO_PID (pid_t)-1 | |
224 | ||
225 | #if !defined (_POSIX_VERSION) && !defined (sigmask) | |
226 | # define sigmask(x) (1 << ((x)-1)) | |
227 | #endif /* !POSIX && !sigmask */ | |
228 | ||
229 | #if !defined (SIGABRT) | |
230 | # define SIGABRT SIGIOT | |
231 | #endif /* !SIGABRT */ | |
232 | ||
233 | #if !defined (SIGCHLD) | |
234 | # define SIGCHLD SIGCLD | |
235 | #endif /* !SIGCHLD */ | |
236 | ||
237 | #if !defined (_POSIX_VERSION) | |
238 | # if !defined (SIG_BLOCK) | |
239 | # define SIG_BLOCK 2 | |
240 | # define SIG_SETMASK 3 | |
241 | # endif /* SIG_BLOCK */ | |
242 | ||
243 | /* Type of a signal set. */ | |
244 | # define sigset_t int | |
245 | ||
246 | /* Make sure there is nothing inside the signal set. */ | |
247 | # define sigemptyset(set) (*(set) = 0) | |
248 | ||
249 | /* Initialize the signal set to hold all signals. */ | |
250 | # define sigfillset(set) (*set) = sigmask (NSIG) - 1 | |
251 | ||
252 | /* Add SIG to the contents of SET. */ | |
253 | # define sigaddset(set, sig) *(set) |= sigmask (sig) | |
254 | ||
255 | /* Delete SIG from signal set SET. */ | |
256 | # define sigdelset(set, sig) *(set) &= ~sigmask (sig) | |
257 | ||
258 | /* Is SIG a member of the signal set SET? */ | |
259 | # define sigismember(set, sig) ((*(set) & sigmask (sig)) != 0) | |
260 | ||
261 | /* Suspend the process until the reception of one of the signals | |
262 | not present in SET. */ | |
263 | # define sigsuspend(set) sigpause (*(set)) | |
264 | #endif /* !_POSIX_VERSION */ | |
265 | ||
266 | /* These definitions are used both in POSIX and non-POSIX implementations. */ | |
267 | ||
268 | #define BLOCK_SIGNAL(sig, nvar, ovar) \ | |
269 | sigemptyset (&nvar); \ | |
270 | sigaddset (&nvar, sig); \ | |
271 | sigemptyset (&ovar); \ | |
272 | sigprocmask (SIG_BLOCK, &nvar, &ovar) | |
273 | ||
274 | #if defined (_POSIX_VERSION) | |
275 | # define BLOCK_CHILD(nvar, ovar) \ | |
276 | BLOCK_SIGNAL (SIGCHLD, nvar, ovar) | |
277 | # define UNBLOCK_CHILD(ovar) \ | |
278 | sigprocmask (SIG_SETMASK, &ovar, (sigset_t *) NULL) | |
279 | #else /* !_POSIX_VERSION */ | |
280 | # define BLOCK_CHILD(nvar, ovar) ovar = sigblock (sigmask (SIGCHLD)) | |
281 | # define UNBLOCK_CHILD(ovar) sigsetmask (ovar) | |
282 | #endif /* !_POSIX_VERSION */ | |
283 | ||
284 | /* System calls. */ | |
285 | #if !defined (SunOS5) && !defined (USGr4_2) && !defined (__BSD_4_4__) | |
286 | extern pid_t fork (), getpid (), getpgrp (); | |
287 | #endif /* !SunOS5 && !USGr4_2 && !__BSD_4_4__ */ | |
288 | ||
289 | /* Stuff from the jobs.c file. */ | |
290 | extern pid_t original_pgrp, shell_pgrp, pipeline_pgrp; | |
291 | extern pid_t last_made_pid, last_asynchronous_pid; | |
292 | extern int current_job, previous_job; | |
293 | extern int asynchronous_notification; | |
294 | extern JOB **jobs; | |
295 | extern int job_slots; | |
296 | ||
297 | extern void making_children __P((void)); | |
298 | extern void stop_making_children __P((void)); | |
299 | extern void cleanup_the_pipeline __P((void)); | |
300 | extern void start_pipeline __P((void)); | |
301 | extern int stop_pipeline __P((int, COMMAND *)); | |
302 | extern void delete_job __P((int)); | |
303 | ||
304 | extern void terminate_current_pipeline __P((void)); | |
305 | extern void terminate_stopped_jobs __P((void)); | |
306 | extern void hangup_all_jobs __P((void)); | |
307 | extern void kill_current_pipeline __P((void)); | |
308 | ||
309 | #if defined (__STDC__) && defined (pid_t) | |
310 | extern void describe_pid __P((int)); | |
311 | #else | |
312 | extern void describe_pid __P((pid_t)); | |
313 | #endif | |
314 | ||
315 | extern int list_one_job __P((JOB *, int, int, int)); | |
316 | extern void list_jobs __P((int)); | |
317 | ||
318 | extern pid_t make_child __P((char *, int)); | |
319 | extern int get_tty_state __P((void)); | |
320 | extern int set_tty_state __P((void)); | |
321 | ||
322 | extern int wait_for_single_pid __P((pid_t)); | |
323 | extern void wait_for_background_pids __P((void)); | |
324 | extern int wait_for __P((pid_t)); | |
325 | extern int wait_for_job __P((int)); | |
326 | ||
327 | extern void notify_and_cleanup __P((void)); | |
328 | extern void reap_dead_jobs __P((void)); | |
329 | extern int start_job __P((int, int)); | |
330 | extern int kill_pid __P((pid_t, int, int)); | |
331 | extern int initialize_jobs __P((void)); | |
332 | extern void initialize_job_signals __P((void)); | |
333 | extern int give_terminal_to __P((pid_t)); | |
334 | ||
335 | extern int set_job_control __P((int)); | |
336 | extern void without_job_control __P((void)); | |
337 | extern void end_job_control __P((void)); | |
338 | extern void restart_job_control __P((void)); | |
339 | extern void set_sigchld_handler __P((void)); | |
340 | ||
341 | #if defined (JOB_CONTROL) | |
342 | extern int job_control; | |
343 | #endif | |
344 | ||
345 | #endif /* __JOBS_H__ */ |