]>
Commit | Line | Data |
---|---|---|
1 | /* jobs.h -- structures and definitions used by the jobs.c file. */ | |
2 | ||
3 | /* Copyright (C) 1993-2009 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 | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation, either version 3 of the License, or | |
10 | (at your option) any later version. | |
11 | ||
12 | Bash is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with Bash. If not, see <http://www.gnu.org/licenses/>. | |
19 | */ | |
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 | #include "posixwait.h" | |
30 | ||
31 | /* Defines controlling the fashion in which jobs are listed. */ | |
32 | #define JLIST_STANDARD 0 | |
33 | #define JLIST_LONG 1 | |
34 | #define JLIST_PID_ONLY 2 | |
35 | #define JLIST_CHANGED_ONLY 3 | |
36 | #define JLIST_NONINTERACTIVE 4 | |
37 | ||
38 | /* I looked it up. For pretty_print_job (). The real answer is 24. */ | |
39 | #define LONGEST_SIGNAL_DESC 24 | |
40 | ||
41 | /* The max time to sleep while retrying fork() on EAGAIN failure */ | |
42 | #define FORKSLEEP_MAX 16 | |
43 | ||
44 | /* We keep an array of jobs. Each entry in the array is a linked list | |
45 | of processes that are piped together. The first process encountered is | |
46 | the group leader. */ | |
47 | ||
48 | /* Values for the `running' field of a struct process. */ | |
49 | #define PS_DONE 0 | |
50 | #define PS_RUNNING 1 | |
51 | #define PS_STOPPED 2 | |
52 | #define PS_RECYCLED 4 | |
53 | ||
54 | /* Each child of the shell is remembered in a STRUCT PROCESS. A circular | |
55 | chain of such structures is a pipeline. */ | |
56 | typedef struct process { | |
57 | struct process *next; /* Next process in the pipeline. A circular chain. */ | |
58 | pid_t pid; /* Process ID. */ | |
59 | WAIT status; /* The status of this command as returned by wait. */ | |
60 | int running; /* Non-zero if this process is running. */ | |
61 | char *command; /* The particular program that is running. */ | |
62 | } PROCESS; | |
63 | ||
64 | /* PALIVE really means `not exited' */ | |
65 | #define PSTOPPED(p) (WIFSTOPPED((p)->status)) | |
66 | #define PRUNNING(p) ((p)->running == PS_RUNNING) | |
67 | #define PALIVE(p) (PRUNNING(p) || PSTOPPED(p)) | |
68 | ||
69 | #define PEXITED(p) ((p)->running == PS_DONE) | |
70 | #if defined (RECYCLES_PIDS) | |
71 | # define PRECYCLED(p) ((p)->running == PS_RECYCLED) | |
72 | #else | |
73 | # define PRECYCLED(p) (0) | |
74 | #endif | |
75 | #define PDEADPROC(p) (PEXITED(p) || PRECYCLED(p)) | |
76 | ||
77 | #define get_job_by_jid(ind) (jobs[(ind)]) | |
78 | ||
79 | /* A description of a pipeline's state. */ | |
80 | typedef enum { JNONE = -1, JRUNNING = 1, JSTOPPED = 2, JDEAD = 4, JMIXED = 8 } JOB_STATE; | |
81 | #define JOBSTATE(job) (jobs[(job)]->state) | |
82 | #define J_JOBSTATE(j) ((j)->state) | |
83 | ||
84 | #define STOPPED(j) (jobs[(j)]->state == JSTOPPED) | |
85 | #define RUNNING(j) (jobs[(j)]->state == JRUNNING) | |
86 | #define DEADJOB(j) (jobs[(j)]->state == JDEAD) | |
87 | ||
88 | #define INVALID_JOB(j) ((j) < 0 || (j) >= js.j_jobslots || get_job_by_jid(j) == 0) | |
89 | ||
90 | /* Values for the FLAGS field in the JOB struct below. */ | |
91 | #define J_FOREGROUND 0x01 /* Non-zero if this is running in the foreground. */ | |
92 | #define J_NOTIFIED 0x02 /* Non-zero if already notified about job state. */ | |
93 | #define J_JOBCONTROL 0x04 /* Non-zero if this job started under job control. */ | |
94 | #define J_NOHUP 0x08 /* Don't send SIGHUP to job if shell gets SIGHUP. */ | |
95 | #define J_STATSAVED 0x10 /* A process in this job had had status saved via $! */ | |
96 | #define J_ASYNC 0x20 /* Job was started asynchronously */ | |
97 | ||
98 | #define IS_FOREGROUND(j) ((jobs[j]->flags & J_FOREGROUND) != 0) | |
99 | #define IS_NOTIFIED(j) ((jobs[j]->flags & J_NOTIFIED) != 0) | |
100 | #define IS_JOBCONTROL(j) ((jobs[j]->flags & J_JOBCONTROL) != 0) | |
101 | #define IS_ASYNC(j) ((jobs[j]->flags & J_ASYNC) != 0) | |
102 | ||
103 | typedef struct job { | |
104 | char *wd; /* The working directory at time of invocation. */ | |
105 | PROCESS *pipe; /* The pipeline of processes that make up this job. */ | |
106 | pid_t pgrp; /* The process ID of the process group (necessary). */ | |
107 | JOB_STATE state; /* The state that this job is in. */ | |
108 | int flags; /* Flags word: J_NOTIFIED, J_FOREGROUND, or J_JOBCONTROL. */ | |
109 | #if defined (JOB_CONTROL) | |
110 | COMMAND *deferred; /* Commands that will execute when this job is done. */ | |
111 | sh_vptrfunc_t *j_cleanup; /* Cleanup function to call when job marked JDEAD */ | |
112 | PTR_T cleanarg; /* Argument passed to (*j_cleanup)() */ | |
113 | #endif /* JOB_CONTROL */ | |
114 | } JOB; | |
115 | ||
116 | struct jobstats { | |
117 | /* limits */ | |
118 | long c_childmax; | |
119 | /* child process statistics */ | |
120 | int c_living; /* running or stopped child processes */ | |
121 | int c_reaped; /* exited child processes still in jobs list */ | |
122 | int c_injobs; /* total number of child processes in jobs list */ | |
123 | /* child process totals */ | |
124 | int c_totforked; /* total number of children this shell has forked */ | |
125 | int c_totreaped; /* total number of children this shell has reaped */ | |
126 | /* job counters and indices */ | |
127 | int j_jobslots; /* total size of jobs array */ | |
128 | int j_lastj; /* last (newest) job allocated */ | |
129 | int j_firstj; /* first (oldest) job allocated */ | |
130 | int j_njobs; /* number of non-NULL jobs in jobs array */ | |
131 | int j_ndead; /* number of JDEAD jobs in jobs array */ | |
132 | /* */ | |
133 | int j_current; /* current job */ | |
134 | int j_previous; /* previous job */ | |
135 | /* */ | |
136 | JOB *j_lastmade; /* last job allocated by stop_pipeline */ | |
137 | JOB *j_lastasync; /* last async job allocated by stop_pipeline */ | |
138 | }; | |
139 | ||
140 | struct pidstat { | |
141 | struct pidstat *next; | |
142 | pid_t pid; | |
143 | int status; | |
144 | }; | |
145 | ||
146 | struct bgpids { | |
147 | struct pidstat *list; | |
148 | struct pidstat *end; | |
149 | int npid; | |
150 | }; | |
151 | ||
152 | #define NO_JOB -1 /* An impossible job array index. */ | |
153 | #define DUP_JOB -2 /* A possible return value for get_job_spec (). */ | |
154 | #define BAD_JOBSPEC -3 /* Bad syntax for job spec. */ | |
155 | ||
156 | /* A value which cannot be a process ID. */ | |
157 | #define NO_PID (pid_t)-1 | |
158 | ||
159 | /* System calls. */ | |
160 | #if !defined (HAVE_UNISTD_H) | |
161 | extern pid_t fork (), getpid (), getpgrp (); | |
162 | #endif /* !HAVE_UNISTD_H */ | |
163 | ||
164 | /* Stuff from the jobs.c file. */ | |
165 | extern struct jobstats js; | |
166 | ||
167 | extern pid_t original_pgrp, shell_pgrp, pipeline_pgrp; | |
168 | extern pid_t last_made_pid, last_asynchronous_pid; | |
169 | extern int asynchronous_notification; | |
170 | ||
171 | extern JOB **jobs; | |
172 | ||
173 | extern void making_children __P((void)); | |
174 | extern void stop_making_children __P((void)); | |
175 | extern void cleanup_the_pipeline __P((void)); | |
176 | extern void save_pipeline __P((int)); | |
177 | extern void restore_pipeline __P((int)); | |
178 | extern void start_pipeline __P((void)); | |
179 | extern int stop_pipeline __P((int, COMMAND *)); | |
180 | extern void append_process __P((char *, pid_t, int, int)); | |
181 | ||
182 | extern void delete_job __P((int, int)); | |
183 | extern void nohup_job __P((int)); | |
184 | extern void delete_all_jobs __P((int)); | |
185 | extern void nohup_all_jobs __P((int)); | |
186 | ||
187 | extern int count_all_jobs __P((void)); | |
188 | ||
189 | extern void terminate_current_pipeline __P((void)); | |
190 | extern void terminate_stopped_jobs __P((void)); | |
191 | extern void hangup_all_jobs __P((void)); | |
192 | extern void kill_current_pipeline __P((void)); | |
193 | ||
194 | #if defined (__STDC__) && defined (pid_t) | |
195 | extern int get_job_by_pid __P((int, int)); | |
196 | extern void describe_pid __P((int)); | |
197 | #else | |
198 | extern int get_job_by_pid __P((pid_t, int)); | |
199 | extern void describe_pid __P((pid_t)); | |
200 | #endif | |
201 | ||
202 | extern void list_one_job __P((JOB *, int, int, int)); | |
203 | extern void list_all_jobs __P((int)); | |
204 | extern void list_stopped_jobs __P((int)); | |
205 | extern void list_running_jobs __P((int)); | |
206 | ||
207 | extern pid_t make_child __P((char *, int)); | |
208 | ||
209 | extern int get_tty_state __P((void)); | |
210 | extern int set_tty_state __P((void)); | |
211 | ||
212 | extern int job_exit_status __P((int)); | |
213 | extern int job_exit_signal __P((int)); | |
214 | ||
215 | extern int wait_for_single_pid __P((pid_t)); | |
216 | extern void wait_for_background_pids __P((void)); | |
217 | extern int wait_for __P((pid_t)); | |
218 | extern int wait_for_job __P((int)); | |
219 | ||
220 | extern void notify_and_cleanup __P((void)); | |
221 | extern void reap_dead_jobs __P((void)); | |
222 | extern int start_job __P((int, int)); | |
223 | extern int kill_pid __P((pid_t, int, int)); | |
224 | extern int initialize_job_control __P((int)); | |
225 | extern void initialize_job_signals __P((void)); | |
226 | extern int give_terminal_to __P((pid_t, int)); | |
227 | ||
228 | extern void run_sigchld_trap __P((int)); | |
229 | ||
230 | extern void freeze_jobs_list __P((void)); | |
231 | extern void unfreeze_jobs_list __P((void)); | |
232 | extern int set_job_control __P((int)); | |
233 | extern void without_job_control __P((void)); | |
234 | extern void end_job_control __P((void)); | |
235 | extern void restart_job_control __P((void)); | |
236 | extern void set_sigchld_handler __P((void)); | |
237 | extern void ignore_tty_job_signals __P((void)); | |
238 | extern void default_tty_job_signals __P((void)); | |
239 | ||
240 | extern void init_job_stats __P((void)); | |
241 | ||
242 | extern void close_pgrp_pipe __P((void)); | |
243 | extern void save_pgrp_pipe __P((int *, int)); | |
244 | extern void restore_pgrp_pipe __P((int *)); | |
245 | ||
246 | #if defined (JOB_CONTROL) | |
247 | extern int job_control; | |
248 | #endif | |
249 | ||
250 | #endif /* _JOBS_H_ */ |