1 1.19 kamil /* $NetBSD: jobs.c,v 1.19 2017/06/30 04:41:19 kamil Exp $ */ 2 1.2 tls 3 1.1 jtc /* 4 1.1 jtc * Process and job control 5 1.1 jtc */ 6 1.1 jtc 7 1.1 jtc /* 8 1.1 jtc * Reworked/Rewritten version of Eric Gisin's/Ron Natalie's code by 9 1.1 jtc * Larry Bouzane (larry (at) cs.mun.ca) and hacked again by 10 1.1 jtc * Michael Rendell (michael (at) cs.mun.ca) 11 1.1 jtc * 12 1.1 jtc * The interface to the rest of the shell should probably be changed 13 1.1 jtc * to allow use of vfork() when available but that would be way too much 14 1.1 jtc * work :) 15 1.1 jtc * 16 1.1 jtc * Notes regarding the copious ifdefs: 17 1.1 jtc * - TTY_PGRP defined iff JOBS is defined - defined if there are tty 18 1.1 jtc * process groups 19 1.1 jtc * - NEED_PGRP_SYNC defined iff JOBS is defined - see comment below 20 1.1 jtc */ 21 1.7 agc #include <sys/cdefs.h> 22 1.7 agc 23 1.7 agc #ifndef lint 24 1.19 kamil __RCSID("$NetBSD: jobs.c,v 1.19 2017/06/30 04:41:19 kamil Exp $"); 25 1.7 agc #endif 26 1.7 agc 27 1.18 kamil #include <sys/stat.h> 28 1.17 kamil #include <sys/times.h> 29 1.15 kamil #include <sys/wait.h> 30 1.1 jtc 31 1.1 jtc #include "sh.h" 32 1.1 jtc #include "tty.h" 33 1.1 jtc 34 1.1 jtc /* Start of system configuration stuff */ 35 1.1 jtc 36 1.1 jtc /* We keep CHILD_MAX zombie processes around (exact value isn't critical) */ 37 1.1 jtc #ifndef CHILD_MAX 38 1.1 jtc # if defined(HAVE_SYSCONF) && defined(_SC_CHILD_MAX) 39 1.1 jtc # define CHILD_MAX sysconf(_SC_CHILD_MAX) 40 1.1 jtc # else /* _SC_CHILD_MAX */ 41 1.1 jtc # ifdef _POSIX_CHILD_MAX 42 1.1 jtc # define CHILD_MAX ((_POSIX_CHILD_MAX) * 2) 43 1.1 jtc # else /* _POSIX_CHILD_MAX */ 44 1.1 jtc # define CHILD_MAX 20 45 1.1 jtc # endif /* _POSIX_CHILD_MAX */ 46 1.1 jtc # endif /* _SC_CHILD_MAX */ 47 1.1 jtc #endif /* !CHILD_MAX */ 48 1.1 jtc 49 1.1 jtc #ifdef JOBS 50 1.1 jtc # if defined(HAVE_TCSETPGRP) || defined(TIOCSPGRP) 51 1.1 jtc # define TTY_PGRP 52 1.1 jtc # endif 53 1.1 jtc # ifdef BSD_PGRP 54 1.1 jtc # define setpgid setpgrp 55 1.1 jtc # define getpgID() getpgrp(0) 56 1.1 jtc # else 57 1.1 jtc # define getpgID() getpgrp() 58 1.1 jtc # endif 59 1.1 jtc # if defined(TTY_PGRP) && !defined(HAVE_TCSETPGRP) 60 1.1 jtc int tcsetpgrp ARGS((int fd, pid_t grp)); 61 1.1 jtc int tcgetpgrp ARGS((int fd)); 62 1.1 jtc 63 1.1 jtc int 64 1.1 jtc tcsetpgrp(fd, grp) 65 1.1 jtc int fd; 66 1.1 jtc pid_t grp; 67 1.1 jtc { 68 1.1 jtc return ioctl(fd, TIOCSPGRP, &grp); 69 1.1 jtc } 70 1.1 jtc 71 1.1 jtc int 72 1.1 jtc tcgetpgrp(fd) 73 1.1 jtc int fd; 74 1.1 jtc { 75 1.1 jtc int r, grp; 76 1.1 jtc 77 1.1 jtc if ((r = ioctl(fd, TIOCGPGRP, &grp)) < 0) 78 1.1 jtc return r; 79 1.1 jtc return grp; 80 1.1 jtc } 81 1.1 jtc # endif /* !HAVE_TCSETPGRP && TIOCSPGRP */ 82 1.1 jtc #else /* JOBS */ 83 1.1 jtc /* These so we can use ifdef xxx instead of if defined(JOBS) && defined(xxx) */ 84 1.1 jtc # undef TTY_PGRP 85 1.1 jtc # undef NEED_PGRP_SYNC 86 1.1 jtc #endif /* JOBS */ 87 1.1 jtc 88 1.1 jtc /* End of system configuration stuff */ 89 1.1 jtc 90 1.1 jtc 91 1.1 jtc /* Order important! */ 92 1.1 jtc #define PRUNNING 0 93 1.1 jtc #define PEXITED 1 94 1.1 jtc #define PSIGNALLED 2 95 1.1 jtc #define PSTOPPED 3 96 1.1 jtc 97 1.1 jtc typedef struct proc Proc; 98 1.1 jtc struct proc { 99 1.1 jtc Proc *next; /* next process in pipeline (if any) */ 100 1.1 jtc int state; 101 1.15 kamil int status; /* wait status */ 102 1.1 jtc pid_t pid; /* process id */ 103 1.1 jtc char command[48]; /* process command string */ 104 1.1 jtc }; 105 1.1 jtc 106 1.1 jtc /* Notify/print flag - j_print() argument */ 107 1.1 jtc #define JP_NONE 0 /* don't print anything */ 108 1.1 jtc #define JP_SHORT 1 /* print signals processes were killed by */ 109 1.1 jtc #define JP_MEDIUM 2 /* print [job-num] -/+ command */ 110 1.1 jtc #define JP_LONG 3 /* print [job-num] -/+ pid command */ 111 1.1 jtc #define JP_PGRP 4 /* print pgrp */ 112 1.1 jtc 113 1.1 jtc /* put_job() flags */ 114 1.1 jtc #define PJ_ON_FRONT 0 /* at very front */ 115 1.1 jtc #define PJ_PAST_STOPPED 1 /* just past any stopped jobs */ 116 1.1 jtc 117 1.1 jtc /* Job.flags values */ 118 1.1 jtc #define JF_STARTED 0x001 /* set when all processes in job are started */ 119 1.1 jtc #define JF_WAITING 0x002 /* set if j_waitj() is waiting on job */ 120 1.1 jtc #define JF_W_ASYNCNOTIFY 0x004 /* set if waiting and async notification ok */ 121 1.1 jtc #define JF_XXCOM 0x008 /* set for `command` jobs */ 122 1.1 jtc #define JF_FG 0x010 /* running in foreground (also has tty pgrp) */ 123 1.1 jtc #define JF_SAVEDTTY 0x020 /* j->ttystate is valid */ 124 1.1 jtc #define JF_CHANGED 0x040 /* process has changed state */ 125 1.1 jtc #define JF_KNOWN 0x080 /* $! referenced */ 126 1.1 jtc #define JF_ZOMBIE 0x100 /* known, unwaited process */ 127 1.8 mycroft #define JF_REMOVE 0x200 /* flagged for removal (j_jobs()/j_noityf()) */ 128 1.1 jtc #define JF_USETTYMODE 0x400 /* tty mode saved if process exits normally */ 129 1.5 hubertf #define JF_SAVEDTTYPGRP 0x800 /* j->saved_ttypgrp is valid */ 130 1.1 jtc 131 1.1 jtc typedef struct job Job; 132 1.1 jtc struct job { 133 1.1 jtc Job *next; /* next job in list */ 134 1.1 jtc int job; /* job number: %n */ 135 1.1 jtc int flags; /* see JF_* */ 136 1.1 jtc int state; /* job state */ 137 1.1 jtc int status; /* exit status of last process */ 138 1.1 jtc pid_t pgrp; /* process group of job */ 139 1.1 jtc pid_t ppid; /* pid of process that forked job */ 140 1.14 kamil int_least32_t age; /* number of jobs started */ 141 1.1 jtc clock_t systime; /* system time used by job */ 142 1.1 jtc clock_t usrtime; /* user time used by job */ 143 1.1 jtc Proc *proc_list; /* process list */ 144 1.1 jtc Proc *last_proc; /* last process in list */ 145 1.2 tls #ifdef KSH 146 1.1 jtc Coproc_id coproc_id; /* 0 or id of coprocess output pipe */ 147 1.2 tls #endif /* KSH */ 148 1.1 jtc #ifdef TTY_PGRP 149 1.1 jtc TTY_state ttystate; /* saved tty state for stopped jobs */ 150 1.5 hubertf pid_t saved_ttypgrp; /* saved tty process group for stopped jobs */ 151 1.1 jtc #endif /* TTY_PGRP */ 152 1.1 jtc }; 153 1.1 jtc 154 1.1 jtc /* Flags for j_waitj() */ 155 1.1 jtc #define JW_NONE 0x00 156 1.1 jtc #define JW_INTERRUPT 0x01 /* ^C will stop the wait */ 157 1.1 jtc #define JW_ASYNCNOTIFY 0x02 /* asynchronous notification during wait ok */ 158 1.1 jtc #define JW_STOPPEDWAIT 0x04 /* wait even if job stopped */ 159 1.1 jtc 160 1.1 jtc /* Error codes for j_lookup() */ 161 1.1 jtc #define JL_OK 0 162 1.1 jtc #define JL_NOSUCH 1 /* no such job */ 163 1.1 jtc #define JL_AMBIG 2 /* %foo or %?foo is ambiguous */ 164 1.1 jtc #define JL_INVALID 3 /* non-pid, non-% job id */ 165 1.1 jtc 166 1.1 jtc static const char *const lookup_msgs[] = { 167 1.1 jtc null, 168 1.1 jtc "no such job", 169 1.1 jtc "ambiguous", 170 1.1 jtc "argument must be %job or process id", 171 1.1 jtc (char *) 0 172 1.1 jtc }; 173 1.1 jtc clock_t j_systime, j_usrtime; /* user and system time of last j_waitjed job */ 174 1.1 jtc 175 1.1 jtc static Job *job_list; /* job list */ 176 1.1 jtc static Job *last_job; 177 1.1 jtc static Job *async_job; 178 1.1 jtc static pid_t async_pid; 179 1.1 jtc 180 1.1 jtc static int nzombie; /* # of zombies owned by this process */ 181 1.14 kamil static int_least32_t njobs; /* # of jobs started */ 182 1.1 jtc static int child_max; /* CHILD_MAX */ 183 1.1 jtc 184 1.1 jtc 185 1.1 jtc /* held_sigchld is set if sigchld occurs before a job is completely started */ 186 1.1 jtc static int held_sigchld; 187 1.1 jtc 188 1.1 jtc #ifdef JOBS 189 1.1 jtc static struct shf *shl_j; 190 1.1 jtc #endif /* JOBS */ 191 1.1 jtc 192 1.1 jtc #ifdef NEED_PGRP_SYNC 193 1.1 jtc /* On some systems, the kernel doesn't count zombie processes when checking 194 1.1 jtc * if a process group is valid, which can cause problems in creating the 195 1.1 jtc * pipeline "cmd1 | cmd2": if cmd1 can die (and go into the zombie state) 196 1.1 jtc * before cmd2 is started, the kernel doesn't allow the setpgid() for cmd2 197 1.1 jtc * to succeed. Solution is to create a pipe between the parent and the first 198 1.1 jtc * process; the first process doesn't do anything until the pipe is closed 199 1.1 jtc * and the parent doesn't close the pipe until all the processes are started. 200 1.1 jtc */ 201 1.1 jtc static int j_sync_pipe[2]; 202 1.1 jtc static int j_sync_open; 203 1.1 jtc #endif /* NEED_PGRP_SYNC */ 204 1.1 jtc 205 1.1 jtc #ifdef TTY_PGRP 206 1.1 jtc static int ttypgrp_ok; /* set if can use tty pgrps */ 207 1.1 jtc static pid_t restore_ttypgrp = -1; 208 1.1 jtc static pid_t our_pgrp; 209 1.1 jtc static int const tt_sigs[] = { SIGTSTP, SIGTTIN, SIGTTOU }; 210 1.1 jtc #endif /* TTY_PGRP */ 211 1.1 jtc 212 1.1 jtc static void j_set_async ARGS((Job *j)); 213 1.1 jtc static void j_startjob ARGS((Job *j)); 214 1.1 jtc static int j_waitj ARGS((Job *j, int flags, const char *where)); 215 1.1 jtc static RETSIGTYPE j_sigchld ARGS((int sig)); 216 1.1 jtc static void j_print ARGS((Job *j, int how, struct shf *shf)); 217 1.1 jtc static Job *j_lookup ARGS((const char *cp, int *ecodep)); 218 1.1 jtc static Job *new_job ARGS((void)); 219 1.1 jtc static Proc *new_proc ARGS((void)); 220 1.1 jtc static void check_job ARGS((Job *j)); 221 1.1 jtc static void put_job ARGS((Job *j, int where)); 222 1.1 jtc static void remove_job ARGS((Job *j, const char *where)); 223 1.6 christos static int kill_job ARGS((Job *j, int sig)); 224 1.1 jtc 225 1.1 jtc /* initialize job control */ 226 1.1 jtc void 227 1.1 jtc j_init(mflagset) 228 1.1 jtc int mflagset; 229 1.1 jtc { 230 1.1 jtc child_max = CHILD_MAX; /* so syscon() isn't always being called */ 231 1.1 jtc 232 1.1 jtc sigemptyset(&sm_default); 233 1.1 jtc sigprocmask(SIG_SETMASK, &sm_default, (sigset_t *) 0); 234 1.1 jtc 235 1.1 jtc sigemptyset(&sm_sigchld); 236 1.1 jtc sigaddset(&sm_sigchld, SIGCHLD); 237 1.1 jtc 238 1.1 jtc setsig(&sigtraps[SIGCHLD], j_sigchld, 239 1.1 jtc SS_RESTORE_ORIG|SS_FORCE|SS_SHTRAP); 240 1.1 jtc 241 1.1 jtc #ifdef JOBS 242 1.1 jtc if (!mflagset && Flag(FTALKING)) 243 1.1 jtc Flag(FMONITOR) = 1; 244 1.1 jtc 245 1.1 jtc /* shl_j is used to do asynchronous notification (used in 246 1.1 jtc * an interrupt handler, so need a distinct shf) 247 1.1 jtc */ 248 1.1 jtc shl_j = shf_fdopen(2, SHF_WR, (struct shf *) 0); 249 1.1 jtc 250 1.1 jtc # ifdef TTY_PGRP 251 1.1 jtc if (Flag(FMONITOR) || Flag(FTALKING)) { 252 1.1 jtc int i; 253 1.1 jtc 254 1.1 jtc /* the TF_SHELL_USES test is a kludge that lets us know if 255 1.1 jtc * if the signals have been changed by the shell. 256 1.1 jtc */ 257 1.1 jtc for (i = NELEM(tt_sigs); --i >= 0; ) { 258 1.1 jtc sigtraps[tt_sigs[i]].flags |= TF_SHELL_USES; 259 1.1 jtc /* j_change() sets this to SS_RESTORE_DFL if FMONITOR */ 260 1.1 jtc setsig(&sigtraps[tt_sigs[i]], SIG_IGN, 261 1.1 jtc SS_RESTORE_IGN|SS_FORCE); 262 1.1 jtc } 263 1.1 jtc } 264 1.1 jtc # endif /* TTY_PGRP */ 265 1.1 jtc 266 1.1 jtc /* j_change() calls tty_init() */ 267 1.1 jtc if (Flag(FMONITOR)) 268 1.1 jtc j_change(); 269 1.1 jtc else 270 1.1 jtc #endif /* JOBS */ 271 1.1 jtc if (Flag(FTALKING)) 272 1.19 kamil tty_init(true); 273 1.1 jtc } 274 1.1 jtc 275 1.1 jtc /* job cleanup before shell exit */ 276 1.1 jtc void 277 1.1 jtc j_exit() 278 1.1 jtc { 279 1.1 jtc /* kill stopped, and possibly running, jobs */ 280 1.1 jtc Job *j; 281 1.1 jtc int killed = 0; 282 1.1 jtc 283 1.1 jtc for (j = job_list; j != (Job *) 0; j = j->next) { 284 1.1 jtc if (j->ppid == procpid 285 1.1 jtc && (j->state == PSTOPPED 286 1.1 jtc || (j->state == PRUNNING 287 1.1 jtc && ((j->flags & JF_FG) 288 1.1 jtc || (Flag(FLOGIN) && !Flag(FNOHUP) 289 1.1 jtc && procpid == kshpid))))) 290 1.1 jtc { 291 1.1 jtc killed = 1; 292 1.6 christos if (j->pgrp == 0) 293 1.6 christos kill_job(j, SIGHUP); 294 1.6 christos else 295 1.6 christos killpg(j->pgrp, SIGHUP); 296 1.1 jtc #ifdef JOBS 297 1.6 christos if (j->state == PSTOPPED) { 298 1.6 christos if (j->pgrp == 0) 299 1.6 christos kill_job(j, SIGCONT); 300 1.6 christos else 301 1.6 christos killpg(j->pgrp, SIGCONT); 302 1.6 christos } 303 1.1 jtc #endif /* JOBS */ 304 1.1 jtc } 305 1.1 jtc } 306 1.1 jtc if (killed) 307 1.1 jtc sleep(1); 308 1.1 jtc j_notify(); 309 1.1 jtc 310 1.1 jtc #ifdef JOBS 311 1.1 jtc # ifdef TTY_PGRP 312 1.1 jtc if (kshpid == procpid && restore_ttypgrp >= 0) { 313 1.1 jtc /* Need to restore the tty pgrp to what it was when the 314 1.1 jtc * shell started up, so that the process that started us 315 1.1 jtc * will be able to access the tty when we are done. 316 1.1 jtc * Also need to restore our process group in case we are 317 1.1 jtc * about to do an exec so that both our parent and the 318 1.1 jtc * process we are to become will be able to access the tty. 319 1.1 jtc */ 320 1.1 jtc tcsetpgrp(tty_fd, restore_ttypgrp); 321 1.1 jtc setpgid(0, restore_ttypgrp); 322 1.1 jtc } 323 1.1 jtc # endif /* TTY_PGRP */ 324 1.1 jtc if (Flag(FMONITOR)) { 325 1.1 jtc Flag(FMONITOR) = 0; 326 1.1 jtc j_change(); 327 1.1 jtc } 328 1.1 jtc #endif /* JOBS */ 329 1.1 jtc } 330 1.1 jtc 331 1.1 jtc #ifdef JOBS 332 1.1 jtc /* turn job control on or off according to Flag(FMONITOR) */ 333 1.1 jtc void 334 1.1 jtc j_change() 335 1.1 jtc { 336 1.1 jtc int i; 337 1.1 jtc 338 1.1 jtc if (Flag(FMONITOR)) { 339 1.1 jtc /* Don't call get_tty() 'til we own the tty process group */ 340 1.19 kamil tty_init(false); 341 1.1 jtc 342 1.1 jtc # ifdef TTY_PGRP 343 1.1 jtc /* no controlling tty, no SIGT* */ 344 1.1 jtc ttypgrp_ok = tty_fd >= 0 && tty_devtty; 345 1.1 jtc 346 1.1 jtc if (ttypgrp_ok && (our_pgrp = getpgID()) < 0) { 347 1.19 kamil warningf(false, "j_init: getpgrp() failed: %s", 348 1.1 jtc strerror(errno)); 349 1.1 jtc ttypgrp_ok = 0; 350 1.1 jtc } 351 1.1 jtc if (ttypgrp_ok) { 352 1.1 jtc setsig(&sigtraps[SIGTTIN], SIG_DFL, 353 1.1 jtc SS_RESTORE_ORIG|SS_FORCE); 354 1.1 jtc /* wait to be given tty (POSIX.1, B.2, job control) */ 355 1.1 jtc while (1) { 356 1.1 jtc pid_t ttypgrp; 357 1.1 jtc 358 1.1 jtc if ((ttypgrp = tcgetpgrp(tty_fd)) < 0) { 359 1.19 kamil warningf(false, 360 1.1 jtc "j_init: tcgetpgrp() failed: %s", 361 1.1 jtc strerror(errno)); 362 1.1 jtc ttypgrp_ok = 0; 363 1.1 jtc break; 364 1.1 jtc } 365 1.1 jtc if (ttypgrp == our_pgrp) 366 1.1 jtc break; 367 1.1 jtc kill(0, SIGTTIN); 368 1.1 jtc } 369 1.1 jtc } 370 1.1 jtc for (i = NELEM(tt_sigs); --i >= 0; ) 371 1.1 jtc setsig(&sigtraps[tt_sigs[i]], SIG_IGN, 372 1.1 jtc SS_RESTORE_DFL|SS_FORCE); 373 1.1 jtc if (ttypgrp_ok && our_pgrp != kshpid) { 374 1.1 jtc if (setpgid(0, kshpid) < 0) { 375 1.19 kamil warningf(false, 376 1.1 jtc "j_init: setpgid() failed: %s", 377 1.1 jtc strerror(errno)); 378 1.1 jtc ttypgrp_ok = 0; 379 1.1 jtc } else { 380 1.1 jtc if (tcsetpgrp(tty_fd, kshpid) < 0) { 381 1.19 kamil warningf(false, 382 1.1 jtc "j_init: tcsetpgrp() failed: %s", 383 1.1 jtc strerror(errno)); 384 1.1 jtc ttypgrp_ok = 0; 385 1.1 jtc } else 386 1.1 jtc restore_ttypgrp = our_pgrp; 387 1.1 jtc our_pgrp = kshpid; 388 1.1 jtc } 389 1.1 jtc } 390 1.1 jtc # if defined(NTTYDISC) && defined(TIOCSETD) && !defined(HAVE_TERMIOS_H) && !defined(HAVE_TERMIO_H) 391 1.1 jtc if (ttypgrp_ok) { 392 1.1 jtc int ldisc = NTTYDISC; 393 1.1 jtc 394 1.1 jtc if (ioctl(tty_fd, TIOCSETD, &ldisc) < 0) 395 1.19 kamil warningf(false, 396 1.1 jtc "j_init: can't set new line discipline: %s", 397 1.1 jtc strerror(errno)); 398 1.1 jtc } 399 1.1 jtc # endif /* NTTYDISC && TIOCSETD */ 400 1.1 jtc if (!ttypgrp_ok) 401 1.19 kamil warningf(false, "warning: won't have full job control"); 402 1.1 jtc # endif /* TTY_PGRP */ 403 1.1 jtc if (tty_fd >= 0) 404 1.1 jtc get_tty(tty_fd, &tty_state); 405 1.1 jtc } else { 406 1.1 jtc # ifdef TTY_PGRP 407 1.1 jtc ttypgrp_ok = 0; 408 1.1 jtc if (Flag(FTALKING)) 409 1.1 jtc for (i = NELEM(tt_sigs); --i >= 0; ) 410 1.1 jtc setsig(&sigtraps[tt_sigs[i]], SIG_IGN, 411 1.1 jtc SS_RESTORE_IGN|SS_FORCE); 412 1.1 jtc else 413 1.1 jtc for (i = NELEM(tt_sigs); --i >= 0; ) { 414 1.1 jtc if (sigtraps[tt_sigs[i]].flags & (TF_ORIG_IGN 415 1.1 jtc |TF_ORIG_DFL)) 416 1.1 jtc setsig(&sigtraps[tt_sigs[i]], 417 1.1 jtc (sigtraps[tt_sigs[i]].flags & TF_ORIG_IGN) ? SIG_IGN : SIG_DFL, 418 1.1 jtc SS_RESTORE_ORIG|SS_FORCE); 419 1.1 jtc } 420 1.1 jtc # endif /* TTY_PGRP */ 421 1.1 jtc if (!Flag(FTALKING)) 422 1.1 jtc tty_close(); 423 1.1 jtc } 424 1.1 jtc } 425 1.1 jtc #endif /* JOBS */ 426 1.1 jtc 427 1.1 jtc /* execute tree in child subprocess */ 428 1.1 jtc int 429 1.1 jtc exchild(t, flags, close_fd) 430 1.1 jtc struct op *t; 431 1.1 jtc int flags; 432 1.1 jtc int close_fd; /* used if XPCLOSE or XCCLOSE */ 433 1.1 jtc { 434 1.1 jtc static Proc *last_proc; /* for pipelines */ 435 1.1 jtc 436 1.1 jtc int i; 437 1.1 jtc sigset_t omask; 438 1.1 jtc Proc *p; 439 1.1 jtc Job *j; 440 1.1 jtc int rv = 0; 441 1.1 jtc int forksleep; 442 1.1 jtc int ischild; 443 1.1 jtc 444 1.1 jtc if (flags & XEXEC) 445 1.5 hubertf /* Clear XFORK|XPCLOSE|XCCLOSE|XCOPROC|XPIPEO|XPIPEI|XXCOM|XBGND 446 1.5 hubertf * (also done in another execute() below) 447 1.5 hubertf */ 448 1.5 hubertf return execute(t, flags & (XEXEC | XERROK)); 449 1.1 jtc 450 1.1 jtc /* no SIGCHLD's while messing with job and process lists */ 451 1.1 jtc sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); 452 1.1 jtc 453 1.1 jtc p = new_proc(); 454 1.1 jtc p->next = (Proc *) 0; 455 1.1 jtc p->state = PRUNNING; 456 1.15 kamil p->status = 0; 457 1.1 jtc p->pid = 0; 458 1.1 jtc 459 1.1 jtc /* link process into jobs list */ 460 1.1 jtc if (flags&XPIPEI) { /* continuing with a pipe */ 461 1.5 hubertf if (!last_job) 462 1.5 hubertf internal_errorf(1, "exchild: XPIPEI and no last_job - pid %d", (int) procpid); 463 1.1 jtc j = last_job; 464 1.1 jtc last_proc->next = p; 465 1.1 jtc last_proc = p; 466 1.1 jtc } else { 467 1.1 jtc #ifdef NEED_PGRP_SYNC 468 1.2 tls if (j_sync_open) { /* should never happen */ 469 1.2 tls j_sync_open = 0; 470 1.1 jtc closepipe(j_sync_pipe); 471 1.1 jtc } 472 1.1 jtc /* don't do the sync pipe business if there is no pipeline */ 473 1.1 jtc if (flags & XPIPEO) { 474 1.1 jtc openpipe(j_sync_pipe); 475 1.1 jtc j_sync_open = 1; 476 1.1 jtc } 477 1.1 jtc #endif /* NEED_PGRP_SYNC */ 478 1.1 jtc j = new_job(); /* fills in j->job */ 479 1.1 jtc /* we don't consider XXCOM's foreground since they don't get 480 1.1 jtc * tty process group and we don't save or restore tty modes. 481 1.1 jtc */ 482 1.1 jtc j->flags = (flags & XXCOM) ? JF_XXCOM 483 1.1 jtc : ((flags & XBGND) ? 0 : (JF_FG|JF_USETTYMODE)); 484 1.1 jtc j->usrtime = j->systime = 0; 485 1.1 jtc j->state = PRUNNING; 486 1.1 jtc j->pgrp = 0; 487 1.1 jtc j->ppid = procpid; 488 1.1 jtc j->age = ++njobs; 489 1.1 jtc j->proc_list = p; 490 1.2 tls #ifdef KSH 491 1.1 jtc j->coproc_id = 0; 492 1.2 tls #endif /* KSH */ 493 1.1 jtc last_job = j; 494 1.1 jtc last_proc = p; 495 1.1 jtc put_job(j, PJ_PAST_STOPPED); 496 1.1 jtc } 497 1.1 jtc 498 1.6 christos snptreef(p->command, sizeof(p->command), "%T", t); 499 1.1 jtc 500 1.1 jtc /* create child process */ 501 1.1 jtc forksleep = 1; 502 1.1 jtc while ((i = fork()) < 0 && errno == EAGAIN && forksleep < 32) { 503 1.1 jtc if (intrsig) /* allow user to ^C out... */ 504 1.1 jtc break; 505 1.1 jtc sleep(forksleep); 506 1.1 jtc forksleep <<= 1; 507 1.1 jtc } 508 1.1 jtc if (i < 0) { 509 1.6 christos kill_job(j, SIGKILL); 510 1.1 jtc remove_job(j, "fork failed"); 511 1.1 jtc #ifdef NEED_PGRP_SYNC 512 1.1 jtc if (j_sync_open) { 513 1.1 jtc closepipe(j_sync_pipe); 514 1.1 jtc j_sync_open = 0; 515 1.1 jtc } 516 1.1 jtc #endif /* NEED_PGRP_SYNC */ 517 1.1 jtc sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); 518 1.1 jtc errorf("cannot fork - try again"); 519 1.1 jtc } 520 1.1 jtc ischild = i == 0; 521 1.1 jtc if (ischild) 522 1.1 jtc p->pid = procpid = getpid(); 523 1.1 jtc else 524 1.1 jtc p->pid = i; 525 1.1 jtc 526 1.1 jtc #ifdef JOBS 527 1.1 jtc /* job control set up */ 528 1.1 jtc if (Flag(FMONITOR) && !(flags&XXCOM)) { 529 1.1 jtc int dotty = 0; 530 1.1 jtc # ifdef NEED_PGRP_SYNC 531 1.2 tls int first_child_sync = 0; 532 1.1 jtc # endif /* NEED_PGRP_SYNC */ 533 1.1 jtc 534 1.1 jtc # ifdef NEED_PGRP_SYNC 535 1.2 tls if (j_sync_open) { 536 1.2 tls /* 537 1.2 tls * The Parent closes 0, keeps 1 open 'til the whole 538 1.2 tls * pipeline is started. The First child closes 1, 539 1.2 tls * keeps 0 open (reads from it). The remaining 540 1.2 tls * children just have to close 1 (parent has already 541 1.2 tls * closeed 0). 542 1.2 tls */ 543 1.2 tls if (j->pgrp == 0) { /* First process */ 544 1.1 jtc close(j_sync_pipe[ischild]); 545 1.1 jtc j_sync_pipe[ischild] = -1; 546 1.2 tls first_child_sync = ischild; 547 1.2 tls } else if (ischild) { 548 1.2 tls j_sync_open = 0; 549 1.2 tls closepipe(j_sync_pipe); 550 1.1 jtc } 551 1.2 tls } 552 1.1 jtc # endif /* NEED_PGRP_SYNC */ 553 1.2 tls if (j->pgrp == 0) { /* First process */ 554 1.2 tls j->pgrp = p->pid; 555 1.2 tls dotty = 1; 556 1.1 jtc } 557 1.1 jtc 558 1.1 jtc /* set pgrp in both parent and child to deal with race 559 1.1 jtc * condition 560 1.1 jtc */ 561 1.1 jtc setpgid(p->pid, j->pgrp); 562 1.1 jtc # ifdef TTY_PGRP 563 1.1 jtc /* YYY: should this be 564 1.1 jtc if (ttypgrp_ok && ischild && !(flags&XBGND)) 565 1.1 jtc tcsetpgrp(tty_fd, j->pgrp); 566 1.1 jtc instead? (see also YYY below) 567 1.1 jtc */ 568 1.1 jtc if (ttypgrp_ok && dotty && !(flags & XBGND)) 569 1.1 jtc tcsetpgrp(tty_fd, j->pgrp); 570 1.1 jtc # endif /* TTY_PGRP */ 571 1.1 jtc # ifdef NEED_PGRP_SYNC 572 1.2 tls if (first_child_sync) { 573 1.2 tls char c; 574 1.2 tls while (read(j_sync_pipe[0], &c, 1) == -1 575 1.2 tls && errno == EINTR) 576 1.2 tls ; 577 1.1 jtc close(j_sync_pipe[0]); 578 1.1 jtc j_sync_open = 0; 579 1.1 jtc } 580 1.1 jtc # endif /* NEED_PGRP_SYNC */ 581 1.1 jtc } 582 1.1 jtc #endif /* JOBS */ 583 1.1 jtc 584 1.1 jtc /* used to close pipe input fd */ 585 1.5 hubertf if (close_fd >= 0 && (((flags & XPCLOSE) && !ischild) 586 1.5 hubertf || ((flags & XCCLOSE) && ischild))) 587 1.1 jtc close(close_fd); 588 1.1 jtc if (ischild) { /* child */ 589 1.1 jtc #ifdef KSH 590 1.1 jtc /* Do this before restoring signal */ 591 1.5 hubertf if (flags & XCOPROC) 592 1.19 kamil coproc_cleanup(false); 593 1.1 jtc #endif /* KSH */ 594 1.1 jtc sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); 595 1.1 jtc cleanup_parents_env(); 596 1.1 jtc #ifdef TTY_PGRP 597 1.1 jtc /* If FMONITOR or FTALKING is set, these signals are ignored, 598 1.1 jtc * if neither FMONITOR nor FTALKING are set, the signals have 599 1.1 jtc * their inherited values. 600 1.1 jtc */ 601 1.1 jtc if (Flag(FMONITOR) && !(flags & XXCOM)) { 602 1.1 jtc for (i = NELEM(tt_sigs); --i >= 0; ) 603 1.1 jtc setsig(&sigtraps[tt_sigs[i]], SIG_DFL, 604 1.1 jtc SS_RESTORE_DFL|SS_FORCE); 605 1.1 jtc } 606 1.1 jtc #endif /* TTY_PGRP */ 607 1.1 jtc #ifdef HAVE_NICE 608 1.1 jtc if (Flag(FBGNICE) && (flags & XBGND)) 609 1.1 jtc nice(4); 610 1.1 jtc #endif /* HAVE_NICE */ 611 1.1 jtc if ((flags & XBGND) && !Flag(FMONITOR)) { 612 1.1 jtc setsig(&sigtraps[SIGINT], SIG_IGN, 613 1.1 jtc SS_RESTORE_IGN|SS_FORCE); 614 1.1 jtc setsig(&sigtraps[SIGQUIT], SIG_IGN, 615 1.1 jtc SS_RESTORE_IGN|SS_FORCE); 616 1.5 hubertf if (!(flags & (XPIPEI | XCOPROC))) { 617 1.5 hubertf int fd = open("/dev/null", 0); 618 1.8 mycroft if (fd != 0) { 619 1.19 kamil (void) ksh_dup2(fd, 0, true); 620 1.8 mycroft close(fd); 621 1.8 mycroft } 622 1.1 jtc } 623 1.1 jtc } 624 1.1 jtc remove_job(j, "child"); /* in case of `jobs` command */ 625 1.1 jtc nzombie = 0; 626 1.1 jtc #ifdef JOBS 627 1.1 jtc ttypgrp_ok = 0; 628 1.1 jtc Flag(FMONITOR) = 0; 629 1.1 jtc #endif /* JOBS */ 630 1.1 jtc Flag(FTALKING) = 0; 631 1.1 jtc tty_close(); 632 1.1 jtc cleartraps(); 633 1.5 hubertf execute(t, (flags & XERROK) | XEXEC); /* no return */ 634 1.1 jtc internal_errorf(0, "exchild: execute() returned"); 635 1.1 jtc unwind(LLEAVE); 636 1.1 jtc /* NOTREACHED */ 637 1.1 jtc } 638 1.1 jtc 639 1.1 jtc /* shell (parent) stuff */ 640 1.5 hubertf /* Ensure next child gets a (slightly) different $RANDOM sequence */ 641 1.5 hubertf change_random(); 642 1.1 jtc if (!(flags & XPIPEO)) { /* last process in a job */ 643 1.1 jtc #ifdef TTY_PGRP 644 1.1 jtc /* YYY: Is this needed? (see also YYY above) 645 1.1 jtc if (Flag(FMONITOR) && !(flags&(XXCOM|XBGND))) 646 1.1 jtc tcsetpgrp(tty_fd, j->pgrp); 647 1.1 jtc */ 648 1.1 jtc #endif /* TTY_PGRP */ 649 1.1 jtc j_startjob(j); 650 1.1 jtc #ifdef KSH 651 1.5 hubertf if (flags & XCOPROC) { 652 1.1 jtc j->coproc_id = coproc.id; 653 1.1 jtc coproc.njobs++; /* n jobs using co-process output */ 654 1.1 jtc coproc.job = (void *) j; /* j using co-process input */ 655 1.1 jtc } 656 1.1 jtc #endif /* KSH */ 657 1.1 jtc if (flags & XBGND) { 658 1.1 jtc j_set_async(j); 659 1.1 jtc if (Flag(FTALKING)) { 660 1.1 jtc shf_fprintf(shl_out, "[%d]", j->job); 661 1.1 jtc for (p = j->proc_list; p; p = p->next) 662 1.1 jtc shf_fprintf(shl_out, " %d", p->pid); 663 1.1 jtc shf_putchar('\n', shl_out); 664 1.1 jtc shf_flush(shl_out); 665 1.1 jtc } 666 1.1 jtc } else 667 1.1 jtc rv = j_waitj(j, JW_NONE, "jw:last proc"); 668 1.1 jtc } 669 1.1 jtc 670 1.1 jtc sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); 671 1.1 jtc 672 1.1 jtc return rv; 673 1.1 jtc } 674 1.1 jtc 675 1.1 jtc /* start the last job: only used for `command` jobs */ 676 1.1 jtc void 677 1.1 jtc startlast() 678 1.1 jtc { 679 1.1 jtc sigset_t omask; 680 1.1 jtc 681 1.1 jtc sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); 682 1.1 jtc 683 1.1 jtc if (last_job) { /* no need to report error - waitlast() will do it */ 684 1.1 jtc /* ensure it isn't removed by check_job() */ 685 1.1 jtc last_job->flags |= JF_WAITING; 686 1.1 jtc j_startjob(last_job); 687 1.1 jtc } 688 1.1 jtc sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); 689 1.1 jtc } 690 1.1 jtc 691 1.1 jtc /* wait for last job: only used for `command` jobs */ 692 1.1 jtc int 693 1.1 jtc waitlast() 694 1.1 jtc { 695 1.1 jtc int rv; 696 1.1 jtc Job *j; 697 1.1 jtc sigset_t omask; 698 1.1 jtc 699 1.1 jtc sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); 700 1.1 jtc 701 1.1 jtc j = last_job; 702 1.1 jtc if (!j || !(j->flags & JF_STARTED)) { 703 1.1 jtc if (!j) 704 1.19 kamil warningf(true, "waitlast: no last job"); 705 1.1 jtc else 706 1.1 jtc internal_errorf(0, "waitlast: not started"); 707 1.1 jtc sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); 708 1.1 jtc return 125; /* not so arbitrary, non-zero value */ 709 1.1 jtc } 710 1.1 jtc 711 1.1 jtc rv = j_waitj(j, JW_NONE, "jw:waitlast"); 712 1.1 jtc 713 1.1 jtc sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); 714 1.1 jtc 715 1.1 jtc return rv; 716 1.1 jtc } 717 1.1 jtc 718 1.1 jtc /* wait for child, interruptable. */ 719 1.1 jtc int 720 1.1 jtc waitfor(cp, sigp) 721 1.1 jtc const char *cp; 722 1.1 jtc int *sigp; 723 1.1 jtc { 724 1.1 jtc int rv; 725 1.1 jtc Job *j; 726 1.1 jtc int ecode; 727 1.1 jtc int flags = JW_INTERRUPT|JW_ASYNCNOTIFY; 728 1.1 jtc sigset_t omask; 729 1.1 jtc 730 1.1 jtc sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); 731 1.1 jtc 732 1.1 jtc *sigp = 0; 733 1.1 jtc 734 1.1 jtc if (cp == (char *) 0) { 735 1.1 jtc /* wait for an unspecified job - always returns 0, so 736 1.1 jtc * don't have to worry about exited/signaled jobs 737 1.1 jtc */ 738 1.1 jtc for (j = job_list; j; j = j->next) 739 1.1 jtc /* at&t ksh will wait for stopped jobs - we don't */ 740 1.1 jtc if (j->ppid == procpid && j->state == PRUNNING) 741 1.1 jtc break; 742 1.1 jtc if (!j) { 743 1.1 jtc sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); 744 1.1 jtc return -1; 745 1.1 jtc } 746 1.1 jtc } else if ((j = j_lookup(cp, &ecode))) { 747 1.1 jtc /* don't report normal job completion */ 748 1.1 jtc flags &= ~JW_ASYNCNOTIFY; 749 1.1 jtc if (j->ppid != procpid) { 750 1.1 jtc sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); 751 1.1 jtc return -1; 752 1.1 jtc } 753 1.1 jtc } else { 754 1.1 jtc sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); 755 1.5 hubertf if (ecode != JL_NOSUCH) 756 1.5 hubertf bi_errorf("%s: %s", cp, lookup_msgs[ecode]); 757 1.5 hubertf return -1; 758 1.1 jtc } 759 1.1 jtc 760 1.1 jtc /* at&t ksh will wait for stopped jobs - we don't */ 761 1.1 jtc rv = j_waitj(j, flags, "jw:waitfor"); 762 1.1 jtc 763 1.1 jtc sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); 764 1.1 jtc 765 1.1 jtc if (rv < 0) /* we were interrupted */ 766 1.1 jtc *sigp = 128 + -rv; 767 1.1 jtc 768 1.1 jtc return rv; 769 1.1 jtc } 770 1.1 jtc 771 1.1 jtc /* kill (built-in) a job */ 772 1.1 jtc int 773 1.1 jtc j_kill(cp, sig) 774 1.1 jtc const char *cp; 775 1.1 jtc int sig; 776 1.1 jtc { 777 1.1 jtc Job *j; 778 1.1 jtc int rv = 0; 779 1.1 jtc int ecode; 780 1.1 jtc sigset_t omask; 781 1.1 jtc 782 1.1 jtc sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); 783 1.1 jtc 784 1.1 jtc if ((j = j_lookup(cp, &ecode)) == (Job *) 0) { 785 1.1 jtc sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); 786 1.1 jtc bi_errorf("%s: %s", cp, lookup_msgs[ecode]); 787 1.1 jtc return 1; 788 1.1 jtc } 789 1.1 jtc 790 1.1 jtc if (j->pgrp == 0) { /* started when !Flag(FMONITOR) */ 791 1.6 christos if (kill_job(j, sig) < 0) { 792 1.6 christos bi_errorf("%s: %s", cp, strerror(errno)); 793 1.6 christos rv = 1; 794 1.6 christos } 795 1.1 jtc } else { 796 1.1 jtc #ifdef JOBS 797 1.1 jtc if (j->state == PSTOPPED && (sig == SIGTERM || sig == SIGHUP)) 798 1.1 jtc (void) killpg(j->pgrp, SIGCONT); 799 1.1 jtc #endif /* JOBS */ 800 1.1 jtc if (killpg(j->pgrp, sig) < 0) { 801 1.1 jtc bi_errorf("%s: %s", cp, strerror(errno)); 802 1.1 jtc rv = 1; 803 1.1 jtc } 804 1.1 jtc } 805 1.1 jtc 806 1.1 jtc sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); 807 1.1 jtc 808 1.1 jtc return rv; 809 1.1 jtc } 810 1.1 jtc 811 1.1 jtc #ifdef JOBS 812 1.1 jtc /* fg and bg built-ins: called only if Flag(FMONITOR) set */ 813 1.1 jtc int 814 1.1 jtc j_resume(cp, bg) 815 1.1 jtc const char *cp; 816 1.1 jtc int bg; 817 1.1 jtc { 818 1.1 jtc Job *j; 819 1.1 jtc Proc *p; 820 1.1 jtc int ecode; 821 1.1 jtc int running; 822 1.1 jtc int rv = 0; 823 1.1 jtc sigset_t omask; 824 1.1 jtc 825 1.1 jtc sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); 826 1.1 jtc 827 1.1 jtc if ((j = j_lookup(cp, &ecode)) == (Job *) 0) { 828 1.1 jtc sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); 829 1.1 jtc bi_errorf("%s: %s", cp, lookup_msgs[ecode]); 830 1.1 jtc return 1; 831 1.1 jtc } 832 1.1 jtc 833 1.1 jtc if (j->pgrp == 0) { 834 1.1 jtc sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); 835 1.1 jtc bi_errorf("job not job-controlled"); 836 1.1 jtc return 1; 837 1.1 jtc } 838 1.1 jtc 839 1.1 jtc if (bg) 840 1.1 jtc shprintf("[%d] ", j->job); 841 1.1 jtc 842 1.1 jtc running = 0; 843 1.1 jtc for (p = j->proc_list; p != (Proc *) 0; p = p->next) { 844 1.1 jtc if (p->state == PSTOPPED) { 845 1.1 jtc p->state = PRUNNING; 846 1.15 kamil p->status = 0; 847 1.1 jtc running = 1; 848 1.1 jtc } 849 1.1 jtc shprintf("%s%s", p->command, p->next ? "| " : null); 850 1.1 jtc } 851 1.10 joerg shprintf("%s", newline); 852 1.1 jtc shf_flush(shl_stdout); 853 1.1 jtc if (running) 854 1.1 jtc j->state = PRUNNING; 855 1.1 jtc 856 1.1 jtc put_job(j, PJ_PAST_STOPPED); 857 1.1 jtc if (bg) 858 1.1 jtc j_set_async(j); 859 1.1 jtc else { 860 1.1 jtc # ifdef TTY_PGRP 861 1.1 jtc /* attach tty to job */ 862 1.1 jtc if (j->state == PRUNNING) { 863 1.1 jtc if (ttypgrp_ok && (j->flags & JF_SAVEDTTY)) { 864 1.1 jtc set_tty(tty_fd, &j->ttystate, TF_NONE); 865 1.1 jtc } 866 1.5 hubertf /* See comment in j_waitj regarding saved_ttypgrp. */ 867 1.5 hubertf if (ttypgrp_ok && tcsetpgrp(tty_fd, (j->flags & JF_SAVEDTTYPGRP) ? j->saved_ttypgrp : j->pgrp) < 0) { 868 1.5 hubertf if (j->flags & JF_SAVEDTTY) { 869 1.1 jtc set_tty(tty_fd, &tty_state, TF_NONE); 870 1.5 hubertf } 871 1.1 jtc sigprocmask(SIG_SETMASK, &omask, 872 1.1 jtc (sigset_t *) 0); 873 1.1 jtc bi_errorf("1st tcsetpgrp(%d, %d) failed: %s", 874 1.5 hubertf tty_fd, (int) ((j->flags & JF_SAVEDTTYPGRP) ? j->saved_ttypgrp : j->pgrp), strerror(errno)); 875 1.1 jtc return 1; 876 1.1 jtc } 877 1.1 jtc } 878 1.1 jtc # endif /* TTY_PGRP */ 879 1.1 jtc j->flags |= JF_FG; 880 1.1 jtc j->flags &= ~JF_KNOWN; 881 1.1 jtc if (j == async_job) 882 1.1 jtc async_job = (Job *) 0; 883 1.1 jtc } 884 1.1 jtc 885 1.1 jtc if (j->state == PRUNNING && killpg(j->pgrp, SIGCONT) < 0) { 886 1.1 jtc int err = errno; 887 1.1 jtc 888 1.1 jtc if (!bg) { 889 1.1 jtc j->flags &= ~JF_FG; 890 1.1 jtc # ifdef TTY_PGRP 891 1.5 hubertf if (ttypgrp_ok && (j->flags & JF_SAVEDTTY)) { 892 1.1 jtc set_tty(tty_fd, &tty_state, TF_NONE); 893 1.5 hubertf } 894 1.1 jtc if (ttypgrp_ok && tcsetpgrp(tty_fd, our_pgrp) < 0) { 895 1.19 kamil warningf(true, 896 1.1 jtc "fg: 2nd tcsetpgrp(%d, %d) failed: %s", 897 1.1 jtc tty_fd, (int) our_pgrp, 898 1.1 jtc strerror(errno)); 899 1.1 jtc } 900 1.1 jtc # endif /* TTY_PGRP */ 901 1.1 jtc } 902 1.1 jtc sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); 903 1.1 jtc bi_errorf("cannot continue job %s: %s", 904 1.1 jtc cp, strerror(err)); 905 1.1 jtc return 1; 906 1.1 jtc } 907 1.1 jtc if (!bg) { 908 1.1 jtc # ifdef TTY_PGRP 909 1.1 jtc if (ttypgrp_ok) { 910 1.5 hubertf j->flags &= ~(JF_SAVEDTTY | JF_SAVEDTTYPGRP); 911 1.1 jtc } 912 1.1 jtc # endif /* TTY_PGRP */ 913 1.1 jtc rv = j_waitj(j, JW_NONE, "jw:resume"); 914 1.1 jtc } 915 1.1 jtc sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); 916 1.1 jtc return rv; 917 1.1 jtc } 918 1.1 jtc #endif /* JOBS */ 919 1.1 jtc 920 1.1 jtc /* are there any running or stopped jobs ? */ 921 1.1 jtc int 922 1.1 jtc j_stopped_running() 923 1.1 jtc { 924 1.1 jtc Job *j; 925 1.1 jtc int which = 0; 926 1.1 jtc 927 1.1 jtc for (j = job_list; j != (Job *) 0; j = j->next) { 928 1.1 jtc #ifdef JOBS 929 1.1 jtc if (j->ppid == procpid && j->state == PSTOPPED) 930 1.1 jtc which |= 1; 931 1.1 jtc #endif /* JOBS */ 932 1.1 jtc if (Flag(FLOGIN) && !Flag(FNOHUP) && procpid == kshpid 933 1.1 jtc && j->ppid == procpid && j->state == PRUNNING) 934 1.1 jtc which |= 2; 935 1.1 jtc } 936 1.1 jtc if (which) { 937 1.1 jtc shellf("You have %s%s%s jobs\n", 938 1.1 jtc which & 1 ? "stopped" : "", 939 1.1 jtc which == 3 ? " and " : "", 940 1.1 jtc which & 2 ? "running" : ""); 941 1.1 jtc return 1; 942 1.1 jtc } 943 1.1 jtc 944 1.1 jtc return 0; 945 1.1 jtc } 946 1.1 jtc 947 1.1 jtc /* list jobs for jobs built-in */ 948 1.1 jtc int 949 1.1 jtc j_jobs(cp, slp, nflag) 950 1.1 jtc const char *cp; 951 1.1 jtc int slp; /* 0: short, 1: long, 2: pgrp */ 952 1.1 jtc int nflag; 953 1.1 jtc { 954 1.1 jtc Job *j, *tmp; 955 1.1 jtc int how; 956 1.1 jtc int zflag = 0; 957 1.1 jtc sigset_t omask; 958 1.1 jtc 959 1.1 jtc sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); 960 1.1 jtc 961 1.1 jtc if (nflag < 0) { /* kludge: print zombies */ 962 1.1 jtc nflag = 0; 963 1.1 jtc zflag = 1; 964 1.1 jtc } 965 1.1 jtc if (cp) { 966 1.1 jtc int ecode; 967 1.1 jtc 968 1.1 jtc if ((j = j_lookup(cp, &ecode)) == (Job *) 0) { 969 1.1 jtc sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); 970 1.1 jtc bi_errorf("%s: %s", cp, lookup_msgs[ecode]); 971 1.1 jtc return 1; 972 1.1 jtc } 973 1.1 jtc } else 974 1.1 jtc j = job_list; 975 1.1 jtc how = slp == 0 ? JP_MEDIUM : (slp == 1 ? JP_LONG : JP_PGRP); 976 1.1 jtc for (; j; j = j->next) { 977 1.1 jtc if ((!(j->flags & JF_ZOMBIE) || zflag) 978 1.1 jtc && (!nflag || (j->flags & JF_CHANGED))) 979 1.1 jtc { 980 1.1 jtc j_print(j, how, shl_stdout); 981 1.1 jtc if (j->state == PEXITED || j->state == PSIGNALLED) 982 1.1 jtc j->flags |= JF_REMOVE; 983 1.1 jtc } 984 1.1 jtc if (cp) 985 1.1 jtc break; 986 1.1 jtc } 987 1.1 jtc /* Remove jobs after printing so there won't be multiple + or - jobs */ 988 1.1 jtc for (j = job_list; j; j = tmp) { 989 1.1 jtc tmp = j->next; 990 1.1 jtc if (j->flags & JF_REMOVE) 991 1.1 jtc remove_job(j, "jobs"); 992 1.1 jtc } 993 1.1 jtc sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); 994 1.1 jtc return 0; 995 1.1 jtc } 996 1.1 jtc 997 1.1 jtc /* list jobs for top-level notification */ 998 1.1 jtc void 999 1.1 jtc j_notify() 1000 1.1 jtc { 1001 1.1 jtc Job *j, *tmp; 1002 1.1 jtc sigset_t omask; 1003 1.1 jtc 1004 1.1 jtc sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); 1005 1.1 jtc for (j = job_list; j; j = j->next) { 1006 1.1 jtc #ifdef JOBS 1007 1.1 jtc if (Flag(FMONITOR) && (j->flags & JF_CHANGED)) 1008 1.1 jtc j_print(j, JP_MEDIUM, shl_out); 1009 1.1 jtc #endif /* JOBS */ 1010 1.1 jtc /* Remove job after doing reports so there aren't 1011 1.1 jtc * multiple +/- jobs. 1012 1.1 jtc */ 1013 1.1 jtc if (j->state == PEXITED || j->state == PSIGNALLED) 1014 1.1 jtc j->flags |= JF_REMOVE; 1015 1.1 jtc } 1016 1.1 jtc for (j = job_list; j; j = tmp) { 1017 1.1 jtc tmp = j->next; 1018 1.1 jtc if (j->flags & JF_REMOVE) 1019 1.1 jtc remove_job(j, "notify"); 1020 1.1 jtc } 1021 1.1 jtc shf_flush(shl_out); 1022 1.1 jtc sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); 1023 1.1 jtc } 1024 1.1 jtc 1025 1.8 mycroft /* Return pid of last process in last asynchronous job */ 1026 1.1 jtc pid_t 1027 1.1 jtc j_async() 1028 1.1 jtc { 1029 1.1 jtc sigset_t omask; 1030 1.1 jtc 1031 1.1 jtc sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); 1032 1.1 jtc 1033 1.1 jtc if (async_job) 1034 1.1 jtc async_job->flags |= JF_KNOWN; 1035 1.1 jtc 1036 1.1 jtc sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); 1037 1.1 jtc 1038 1.1 jtc return async_pid; 1039 1.1 jtc } 1040 1.1 jtc 1041 1.1 jtc /* Make j the last async process 1042 1.1 jtc * 1043 1.1 jtc * If jobs are compiled in then this routine expects sigchld to be blocked. 1044 1.1 jtc */ 1045 1.1 jtc static void 1046 1.1 jtc j_set_async(j) 1047 1.1 jtc Job *j; 1048 1.1 jtc { 1049 1.1 jtc Job *jl, *oldest; 1050 1.1 jtc 1051 1.1 jtc if (async_job && (async_job->flags & (JF_KNOWN|JF_ZOMBIE)) == JF_ZOMBIE) 1052 1.1 jtc remove_job(async_job, "async"); 1053 1.1 jtc if (!(j->flags & JF_STARTED)) { 1054 1.1 jtc internal_errorf(0, "j_async: job not started"); 1055 1.1 jtc return; 1056 1.1 jtc } 1057 1.1 jtc async_job = j; 1058 1.1 jtc async_pid = j->last_proc->pid; 1059 1.1 jtc while (nzombie > child_max) { 1060 1.1 jtc oldest = (Job *) 0; 1061 1.1 jtc for (jl = job_list; jl; jl = jl->next) 1062 1.1 jtc if (jl != async_job && (jl->flags & JF_ZOMBIE) 1063 1.1 jtc && (!oldest || jl->age < oldest->age)) 1064 1.1 jtc oldest = jl; 1065 1.1 jtc if (!oldest) { 1066 1.1 jtc /* XXX debugging */ 1067 1.1 jtc if (!(async_job->flags & JF_ZOMBIE) || nzombie != 1) { 1068 1.1 jtc internal_errorf(0, "j_async: bad nzombie (%d)", nzombie); 1069 1.1 jtc nzombie = 0; 1070 1.1 jtc } 1071 1.1 jtc break; 1072 1.1 jtc } 1073 1.1 jtc remove_job(oldest, "zombie"); 1074 1.1 jtc } 1075 1.1 jtc } 1076 1.1 jtc 1077 1.1 jtc /* Start a job: set STARTED, check for held signals and set j->last_proc 1078 1.1 jtc * 1079 1.1 jtc * If jobs are compiled in then this routine expects sigchld to be blocked. 1080 1.1 jtc */ 1081 1.1 jtc static void 1082 1.1 jtc j_startjob(j) 1083 1.1 jtc Job *j; 1084 1.1 jtc { 1085 1.1 jtc Proc *p; 1086 1.1 jtc 1087 1.1 jtc j->flags |= JF_STARTED; 1088 1.1 jtc for (p = j->proc_list; p->next; p = p->next) 1089 1.1 jtc ; 1090 1.1 jtc j->last_proc = p; 1091 1.1 jtc 1092 1.1 jtc #ifdef NEED_PGRP_SYNC 1093 1.1 jtc if (j_sync_open) { 1094 1.2 tls j_sync_open = 0; 1095 1.1 jtc closepipe(j_sync_pipe); 1096 1.1 jtc } 1097 1.1 jtc #endif /* NEED_PGRP_SYNC */ 1098 1.1 jtc if (held_sigchld) { 1099 1.1 jtc held_sigchld = 0; 1100 1.2 tls /* Don't call j_sigchld() as it may remove job... */ 1101 1.1 jtc kill(procpid, SIGCHLD); 1102 1.1 jtc } 1103 1.1 jtc } 1104 1.1 jtc 1105 1.1 jtc /* 1106 1.1 jtc * wait for job to complete or change state 1107 1.1 jtc * 1108 1.1 jtc * If jobs are compiled in then this routine expects sigchld to be blocked. 1109 1.1 jtc */ 1110 1.1 jtc static int 1111 1.1 jtc j_waitj(j, flags, where) 1112 1.1 jtc Job *j; 1113 1.1 jtc int flags; /* see JW_* */ 1114 1.1 jtc const char *where; 1115 1.1 jtc { 1116 1.1 jtc int rv; 1117 1.1 jtc 1118 1.1 jtc /* 1119 1.1 jtc * No auto-notify on the job we are waiting on. 1120 1.1 jtc */ 1121 1.1 jtc j->flags |= JF_WAITING; 1122 1.1 jtc if (flags & JW_ASYNCNOTIFY) 1123 1.1 jtc j->flags |= JF_W_ASYNCNOTIFY; 1124 1.1 jtc 1125 1.1 jtc if (!Flag(FMONITOR)) 1126 1.1 jtc flags |= JW_STOPPEDWAIT; 1127 1.1 jtc 1128 1.1 jtc while ((volatile int) j->state == PRUNNING 1129 1.1 jtc || ((flags & JW_STOPPEDWAIT) 1130 1.1 jtc && (volatile int) j->state == PSTOPPED)) 1131 1.1 jtc { 1132 1.1 jtc sigsuspend(&sm_default); 1133 1.1 jtc if (fatal_trap) { 1134 1.1 jtc int oldf = j->flags & (JF_WAITING|JF_W_ASYNCNOTIFY); 1135 1.1 jtc j->flags &= ~(JF_WAITING|JF_W_ASYNCNOTIFY); 1136 1.1 jtc runtraps(TF_FATAL); 1137 1.1 jtc j->flags |= oldf; /* not reached... */ 1138 1.1 jtc } 1139 1.1 jtc if ((flags & JW_INTERRUPT) && (rv = trap_pending())) { 1140 1.1 jtc j->flags &= ~(JF_WAITING|JF_W_ASYNCNOTIFY); 1141 1.1 jtc return -rv; 1142 1.1 jtc } 1143 1.1 jtc } 1144 1.1 jtc j->flags &= ~(JF_WAITING|JF_W_ASYNCNOTIFY); 1145 1.1 jtc 1146 1.1 jtc if (j->flags & JF_FG) { 1147 1.15 kamil int status; 1148 1.1 jtc 1149 1.1 jtc j->flags &= ~JF_FG; 1150 1.1 jtc #ifdef TTY_PGRP 1151 1.1 jtc if (Flag(FMONITOR) && ttypgrp_ok && j->pgrp) { 1152 1.5 hubertf /* 1153 1.5 hubertf * Save the tty's current pgrp so it can be restored 1154 1.5 hubertf * when the job is foregrounded. This is to 1155 1.5 hubertf * deal with things like the GNU su which does 1156 1.5 hubertf * a fork/exec instead of an exec (the fork means 1157 1.5 hubertf * the execed shell gets a different pid from its 1158 1.5 hubertf * pgrp, so naturally it sets its pgrp and gets hosed 1159 1.8 mycroft * when it gets foregrounded by the parent shell, which 1160 1.5 hubertf * has restored the tty's pgrp to that of the su 1161 1.5 hubertf * process). 1162 1.5 hubertf */ 1163 1.5 hubertf if (j->state == PSTOPPED 1164 1.5 hubertf && (j->saved_ttypgrp = tcgetpgrp(tty_fd)) >= 0) 1165 1.5 hubertf j->flags |= JF_SAVEDTTYPGRP; 1166 1.1 jtc if (tcsetpgrp(tty_fd, our_pgrp) < 0) { 1167 1.19 kamil warningf(true, 1168 1.1 jtc "j_waitj: tcsetpgrp(%d, %d) failed: %s", 1169 1.1 jtc tty_fd, (int) our_pgrp, 1170 1.1 jtc strerror(errno)); 1171 1.1 jtc } 1172 1.1 jtc if (j->state == PSTOPPED) { 1173 1.1 jtc j->flags |= JF_SAVEDTTY; 1174 1.1 jtc get_tty(tty_fd, &j->ttystate); 1175 1.1 jtc } 1176 1.1 jtc } 1177 1.1 jtc #endif /* TTY_PGRP */ 1178 1.1 jtc if (tty_fd >= 0) { 1179 1.1 jtc /* Only restore tty settings if job was originally 1180 1.1 jtc * started in the foreground. Problems can be 1181 1.1 jtc * caused by things like `more foobar &' which will 1182 1.1 jtc * typically get and save the shell's vi/emacs tty 1183 1.1 jtc * settings before setting up the tty for itself; 1184 1.1 jtc * when more exits, it restores the `original' 1185 1.1 jtc * settings, and things go down hill from there... 1186 1.1 jtc */ 1187 1.1 jtc if (j->state == PEXITED && j->status == 0 1188 1.1 jtc && (j->flags & JF_USETTYMODE)) 1189 1.1 jtc { 1190 1.1 jtc get_tty(tty_fd, &tty_state); 1191 1.1 jtc } else { 1192 1.1 jtc set_tty(tty_fd, &tty_state, 1193 1.1 jtc (j->state == PEXITED) ? 0 : TF_MIPSKLUDGE); 1194 1.1 jtc /* Don't use tty mode if job is stopped and 1195 1.1 jtc * later restarted and exits. Consider 1196 1.1 jtc * the sequence: 1197 1.1 jtc * vi foo (stopped) 1198 1.1 jtc * ... 1199 1.1 jtc * stty something 1200 1.1 jtc * ... 1201 1.1 jtc * fg (vi; ZZ) 1202 1.1 jtc * mode should be that of the stty, not what 1203 1.1 jtc * was before the vi started. 1204 1.1 jtc */ 1205 1.1 jtc if (j->state == PSTOPPED) 1206 1.1 jtc j->flags &= ~JF_USETTYMODE; 1207 1.1 jtc } 1208 1.1 jtc } 1209 1.1 jtc #ifdef JOBS 1210 1.1 jtc /* If it looks like user hit ^C to kill a job, pretend we got 1211 1.1 jtc * one too to break out of for loops, etc. (at&t ksh does this 1212 1.1 jtc * even when not monitoring, but this doesn't make sense since 1213 1.1 jtc * a tty generated ^C goes to the whole process group) 1214 1.1 jtc */ 1215 1.1 jtc status = j->last_proc->status; 1216 1.1 jtc if (Flag(FMONITOR) && j->state == PSIGNALLED 1217 1.1 jtc && WIFSIGNALED(status) 1218 1.1 jtc && (sigtraps[WTERMSIG(status)].flags & TF_TTY_INTR)) 1219 1.1 jtc trapsig(WTERMSIG(status)); 1220 1.1 jtc #endif /* JOBS */ 1221 1.1 jtc } 1222 1.1 jtc 1223 1.1 jtc j_usrtime = j->usrtime; 1224 1.1 jtc j_systime = j->systime; 1225 1.1 jtc rv = j->status; 1226 1.1 jtc 1227 1.8 mycroft if (!(flags & JW_ASYNCNOTIFY) 1228 1.1 jtc && (!Flag(FMONITOR) || j->state != PSTOPPED)) 1229 1.1 jtc { 1230 1.1 jtc j_print(j, JP_SHORT, shl_out); 1231 1.1 jtc shf_flush(shl_out); 1232 1.1 jtc } 1233 1.1 jtc if (j->state != PSTOPPED 1234 1.1 jtc && (!Flag(FMONITOR) || !(flags & JW_ASYNCNOTIFY))) 1235 1.1 jtc remove_job(j, where); 1236 1.1 jtc 1237 1.1 jtc return rv; 1238 1.1 jtc } 1239 1.1 jtc 1240 1.1 jtc /* SIGCHLD handler to reap children and update job states 1241 1.1 jtc * 1242 1.1 jtc * If jobs are compiled in then this routine expects sigchld to be blocked. 1243 1.1 jtc */ 1244 1.1 jtc static RETSIGTYPE 1245 1.1 jtc j_sigchld(sig) 1246 1.1 jtc int sig; 1247 1.1 jtc { 1248 1.1 jtc int errno_ = errno; 1249 1.1 jtc Job *j; 1250 1.1 jtc Proc UNINITIALIZED(*p); 1251 1.1 jtc int pid; 1252 1.15 kamil int status; 1253 1.1 jtc struct tms t0, t1; 1254 1.1 jtc 1255 1.1 jtc /* Don't wait for any processes if a job is partially started. 1256 1.1 jtc * This is so we don't do away with the process group leader 1257 1.1 jtc * before all the processes in a pipe line are started (so the 1258 1.1 jtc * setpgid() won't fail) 1259 1.1 jtc */ 1260 1.1 jtc for (j = job_list; j; j = j->next) 1261 1.1 jtc if (j->ppid == procpid && !(j->flags & JF_STARTED)) { 1262 1.1 jtc held_sigchld = 1; 1263 1.1 jtc return RETSIGVAL; 1264 1.1 jtc } 1265 1.1 jtc 1266 1.17 kamil times(&t0); 1267 1.1 jtc do { 1268 1.15 kamil pid = waitpid(-1, &status, (WNOHANG|WUNTRACED)); 1269 1.1 jtc 1270 1.1 jtc if (pid <= 0) /* return if would block (0) ... */ 1271 1.1 jtc break; /* ... or no children or interrupted (-1) */ 1272 1.1 jtc 1273 1.17 kamil times(&t1); 1274 1.1 jtc 1275 1.1 jtc /* find job and process structures for this pid */ 1276 1.1 jtc for (j = job_list; j != (Job *) 0; j = j->next) 1277 1.1 jtc for (p = j->proc_list; p != (Proc *) 0; p = p->next) 1278 1.1 jtc if (p->pid == pid) 1279 1.1 jtc goto found; 1280 1.1 jtc found: 1281 1.1 jtc if (j == (Job *) 0) { 1282 1.1 jtc /* Can occur if process has kids, then execs shell 1283 1.19 kamil warningf(true, "bad process waited for (pid = %d)", 1284 1.1 jtc pid); 1285 1.1 jtc */ 1286 1.1 jtc t0 = t1; 1287 1.1 jtc continue; 1288 1.1 jtc } 1289 1.1 jtc 1290 1.1 jtc j->usrtime += t1.tms_cutime - t0.tms_cutime; 1291 1.1 jtc j->systime += t1.tms_cstime - t0.tms_cstime; 1292 1.1 jtc t0 = t1; 1293 1.1 jtc p->status = status; 1294 1.1 jtc #ifdef JOBS 1295 1.1 jtc if (WIFSTOPPED(status)) 1296 1.1 jtc p->state = PSTOPPED; 1297 1.1 jtc else 1298 1.1 jtc #endif /* JOBS */ 1299 1.1 jtc if (WIFSIGNALED(status)) 1300 1.1 jtc p->state = PSIGNALLED; 1301 1.1 jtc else 1302 1.1 jtc p->state = PEXITED; 1303 1.1 jtc 1304 1.1 jtc check_job(j); /* check to see if entire job is done */ 1305 1.1 jtc } 1306 1.1 jtc while (1); 1307 1.1 jtc 1308 1.1 jtc errno = errno_; 1309 1.1 jtc 1310 1.1 jtc return RETSIGVAL; 1311 1.1 jtc } 1312 1.1 jtc 1313 1.1 jtc /* 1314 1.1 jtc * Called only when a process in j has exited/stopped (ie, called only 1315 1.2 tls * from j_sigchld()). If no processes are running, the job status 1316 1.1 jtc * and state are updated, asynchronous job notification is done and, 1317 1.1 jtc * if unneeded, the job is removed. 1318 1.1 jtc * 1319 1.1 jtc * If jobs are compiled in then this routine expects sigchld to be blocked. 1320 1.1 jtc */ 1321 1.1 jtc static void 1322 1.1 jtc check_job(j) 1323 1.1 jtc Job *j; 1324 1.1 jtc { 1325 1.1 jtc int jstate; 1326 1.1 jtc Proc *p; 1327 1.1 jtc 1328 1.1 jtc /* XXX debugging (nasty - interrupt routine using shl_out) */ 1329 1.1 jtc if (!(j->flags & JF_STARTED)) { 1330 1.1 jtc internal_errorf(0, "check_job: job started (flags 0x%x)", 1331 1.1 jtc j->flags); 1332 1.1 jtc return; 1333 1.1 jtc } 1334 1.1 jtc 1335 1.1 jtc jstate = PRUNNING; 1336 1.1 jtc for (p=j->proc_list; p != (Proc *) 0; p = p->next) { 1337 1.1 jtc if (p->state == PRUNNING) 1338 1.1 jtc return; /* some processes still running */ 1339 1.1 jtc if (p->state > jstate) 1340 1.1 jtc jstate = p->state; 1341 1.1 jtc } 1342 1.1 jtc j->state = jstate; 1343 1.1 jtc 1344 1.1 jtc switch (j->last_proc->state) { 1345 1.1 jtc case PEXITED: 1346 1.1 jtc j->status = WEXITSTATUS(j->last_proc->status); 1347 1.1 jtc break; 1348 1.1 jtc case PSIGNALLED: 1349 1.1 jtc j->status = 128 + WTERMSIG(j->last_proc->status); 1350 1.1 jtc break; 1351 1.1 jtc default: 1352 1.1 jtc j->status = 0; 1353 1.1 jtc break; 1354 1.1 jtc } 1355 1.1 jtc 1356 1.1 jtc #ifdef KSH 1357 1.1 jtc /* Note when co-process dies: can't be done in j_wait() nor 1358 1.8 mycroft * remove_job() since neither may be called for non-interactive 1359 1.1 jtc * shells. 1360 1.1 jtc */ 1361 1.1 jtc if (j->state == PEXITED || j->state == PSIGNALLED) { 1362 1.1 jtc /* No need to keep co-process input any more 1363 1.8 mycroft * (at least, this is what ksh93d thinks) 1364 1.1 jtc */ 1365 1.1 jtc if (coproc.job == j) { 1366 1.1 jtc coproc.job = (void *) 0; 1367 1.1 jtc /* XXX would be nice to get the closes out of here 1368 1.1 jtc * so they aren't done in the signal handler. 1369 1.1 jtc * Would mean a check in coproc_getfd() to 1370 1.1 jtc * do "if job == 0 && write >= 0, close write". 1371 1.1 jtc */ 1372 1.1 jtc coproc_write_close(coproc.write); 1373 1.1 jtc } 1374 1.1 jtc /* Do we need to keep the output? */ 1375 1.1 jtc if (j->coproc_id && j->coproc_id == coproc.id 1376 1.1 jtc && --coproc.njobs == 0) 1377 1.1 jtc coproc_readw_close(coproc.read); 1378 1.1 jtc } 1379 1.1 jtc #endif /* KSH */ 1380 1.1 jtc 1381 1.1 jtc j->flags |= JF_CHANGED; 1382 1.1 jtc #ifdef JOBS 1383 1.1 jtc if (Flag(FMONITOR) && !(j->flags & JF_XXCOM)) { 1384 1.1 jtc /* Only put stopped jobs at the front to avoid confusing 1385 1.1 jtc * the user (don't want finished jobs effecting %+ or %-) 1386 1.1 jtc */ 1387 1.1 jtc if (j->state == PSTOPPED) 1388 1.1 jtc put_job(j, PJ_ON_FRONT); 1389 1.1 jtc if (Flag(FNOTIFY) 1390 1.1 jtc && (j->flags & (JF_WAITING|JF_W_ASYNCNOTIFY)) != JF_WAITING) 1391 1.1 jtc { 1392 1.1 jtc /* Look for the real file descriptor 2 */ 1393 1.1 jtc { 1394 1.1 jtc struct env *ep; 1395 1.1 jtc int fd = 2; 1396 1.1 jtc 1397 1.1 jtc for (ep = e; ep; ep = ep->oenv) 1398 1.1 jtc if (ep->savefd && ep->savefd[2]) 1399 1.1 jtc fd = ep->savefd[2]; 1400 1.1 jtc shf_reopen(fd, SHF_WR, shl_j); 1401 1.1 jtc } 1402 1.1 jtc /* Can't call j_notify() as it removes jobs. The job 1403 1.1 jtc * must stay in the job list as j_waitj() may be 1404 1.1 jtc * running with this job. 1405 1.1 jtc */ 1406 1.1 jtc j_print(j, JP_MEDIUM, shl_j); 1407 1.1 jtc shf_flush(shl_j); 1408 1.1 jtc if (!(j->flags & JF_WAITING) && j->state != PSTOPPED) 1409 1.1 jtc remove_job(j, "notify"); 1410 1.1 jtc } 1411 1.1 jtc } 1412 1.1 jtc #endif /* JOBS */ 1413 1.1 jtc if (!Flag(FMONITOR) && !(j->flags & (JF_WAITING|JF_FG)) 1414 1.1 jtc && j->state != PSTOPPED) 1415 1.1 jtc { 1416 1.1 jtc if (j == async_job || (j->flags & JF_KNOWN)) { 1417 1.1 jtc j->flags |= JF_ZOMBIE; 1418 1.1 jtc j->job = -1; 1419 1.1 jtc nzombie++; 1420 1.1 jtc } else 1421 1.1 jtc remove_job(j, "checkjob"); 1422 1.1 jtc } 1423 1.1 jtc } 1424 1.1 jtc 1425 1.1 jtc /* 1426 1.1 jtc * Print job status in either short, medium or long format. 1427 1.1 jtc * 1428 1.1 jtc * If jobs are compiled in then this routine expects sigchld to be blocked. 1429 1.1 jtc */ 1430 1.1 jtc static void 1431 1.1 jtc j_print(j, how, shf) 1432 1.1 jtc Job *j; 1433 1.1 jtc int how; 1434 1.1 jtc struct shf *shf; 1435 1.1 jtc { 1436 1.1 jtc Proc *p; 1437 1.1 jtc int state; 1438 1.15 kamil int status; 1439 1.1 jtc int coredumped; 1440 1.1 jtc char jobchar = ' '; 1441 1.1 jtc char buf[64]; 1442 1.1 jtc const char *filler; 1443 1.1 jtc int output = 0; 1444 1.1 jtc 1445 1.1 jtc if (how == JP_PGRP) { 1446 1.1 jtc /* POSIX doesn't say what to do it there is no process 1447 1.1 jtc * group leader (ie, !FMONITOR). We arbitrarily return 1448 1.1 jtc * last pid (which is what $! returns). 1449 1.1 jtc */ 1450 1.1 jtc shf_fprintf(shf, "%d\n", j->pgrp ? j->pgrp 1451 1.1 jtc : (j->last_proc ? j->last_proc->pid : 0)); 1452 1.1 jtc return; 1453 1.1 jtc } 1454 1.1 jtc j->flags &= ~JF_CHANGED; 1455 1.1 jtc filler = j->job > 10 ? "\n " : "\n "; 1456 1.1 jtc if (j == job_list) 1457 1.1 jtc jobchar = '+'; 1458 1.1 jtc else if (j == job_list->next) 1459 1.1 jtc jobchar = '-'; 1460 1.1 jtc 1461 1.1 jtc for (p = j->proc_list; p != (Proc *) 0;) { 1462 1.1 jtc coredumped = 0; 1463 1.1 jtc switch (p->state) { 1464 1.1 jtc case PRUNNING: 1465 1.8 mycroft strlcpy(buf, "Running", sizeof buf); 1466 1.1 jtc break; 1467 1.1 jtc case PSTOPPED: 1468 1.8 mycroft strlcpy(buf, sigtraps[WSTOPSIG(p->status)].mess, 1469 1.8 mycroft sizeof buf); 1470 1.1 jtc break; 1471 1.1 jtc case PEXITED: 1472 1.1 jtc if (how == JP_SHORT) 1473 1.1 jtc buf[0] = '\0'; 1474 1.1 jtc else if (WEXITSTATUS(p->status) == 0) 1475 1.8 mycroft strlcpy(buf, "Done", sizeof buf); 1476 1.1 jtc else 1477 1.1 jtc shf_snprintf(buf, sizeof(buf), "Done (%d)", 1478 1.1 jtc WEXITSTATUS(p->status)); 1479 1.1 jtc break; 1480 1.1 jtc case PSIGNALLED: 1481 1.15 kamil if (WCOREDUMP(p->status)) 1482 1.1 jtc coredumped = 1; 1483 1.1 jtc /* kludge for not reporting `normal termination signals' 1484 1.1 jtc * (ie, SIGINT, SIGPIPE) 1485 1.1 jtc */ 1486 1.1 jtc if (how == JP_SHORT && !coredumped 1487 1.1 jtc && (WTERMSIG(p->status) == SIGINT 1488 1.1 jtc || WTERMSIG(p->status) == SIGPIPE)) { 1489 1.1 jtc buf[0] = '\0'; 1490 1.1 jtc } else 1491 1.8 mycroft strlcpy(buf, sigtraps[WTERMSIG(p->status)].mess, 1492 1.8 mycroft sizeof buf); 1493 1.1 jtc break; 1494 1.1 jtc } 1495 1.1 jtc 1496 1.4 thorpej if (how != JP_SHORT) { 1497 1.1 jtc if (p == j->proc_list) 1498 1.1 jtc shf_fprintf(shf, "[%d] %c ", j->job, jobchar); 1499 1.1 jtc else 1500 1.1 jtc shf_fprintf(shf, "%s", filler); 1501 1.4 thorpej } 1502 1.1 jtc 1503 1.1 jtc if (how == JP_LONG) 1504 1.1 jtc shf_fprintf(shf, "%5d ", p->pid); 1505 1.1 jtc 1506 1.1 jtc if (how == JP_SHORT) { 1507 1.1 jtc if (buf[0]) { 1508 1.1 jtc output = 1; 1509 1.1 jtc shf_fprintf(shf, "%s%s ", 1510 1.1 jtc buf, coredumped ? " (core dumped)" : null); 1511 1.1 jtc } 1512 1.1 jtc } else { 1513 1.1 jtc output = 1; 1514 1.1 jtc shf_fprintf(shf, "%-20s %s%s%s", buf, p->command, 1515 1.1 jtc p->next ? "|" : null, 1516 1.1 jtc coredumped ? " (core dumped)" : null); 1517 1.1 jtc } 1518 1.1 jtc 1519 1.1 jtc state = p->state; 1520 1.1 jtc status = p->status; 1521 1.1 jtc p = p->next; 1522 1.15 kamil while (p && p->state == state && p->status == status) 1523 1.1 jtc { 1524 1.1 jtc if (how == JP_LONG) 1525 1.1 jtc shf_fprintf(shf, "%s%5d %-20s %s%s", filler, p->pid, 1526 1.1 jtc space, p->command, p->next ? "|" : null); 1527 1.1 jtc else if (how == JP_MEDIUM) 1528 1.1 jtc shf_fprintf(shf, " %s%s", p->command, 1529 1.1 jtc p->next ? "|" : null); 1530 1.1 jtc p = p->next; 1531 1.1 jtc } 1532 1.1 jtc } 1533 1.1 jtc if (output) 1534 1.1 jtc shf_fprintf(shf, newline); 1535 1.1 jtc } 1536 1.1 jtc 1537 1.1 jtc /* Convert % sequence to job 1538 1.1 jtc * 1539 1.1 jtc * If jobs are compiled in then this routine expects sigchld to be blocked. 1540 1.1 jtc */ 1541 1.1 jtc static Job * 1542 1.1 jtc j_lookup(cp, ecodep) 1543 1.1 jtc const char *cp; 1544 1.1 jtc int *ecodep; 1545 1.1 jtc { 1546 1.1 jtc Job *j, *last_match; 1547 1.1 jtc Proc *p; 1548 1.1 jtc int len, job = 0; 1549 1.1 jtc 1550 1.1 jtc if (digit(*cp)) { 1551 1.1 jtc job = atoi(cp); 1552 1.1 jtc /* Look for last_proc->pid (what $! returns) first... */ 1553 1.1 jtc for (j = job_list; j != (Job *) 0; j = j->next) 1554 1.1 jtc if (j->last_proc && j->last_proc->pid == job) 1555 1.1 jtc return j; 1556 1.1 jtc /* ...then look for process group (this is non-POSIX), 1557 1.1 jtc * but should not break anything (so FPOSIX isn't used). 1558 1.1 jtc */ 1559 1.1 jtc for (j = job_list; j != (Job *) 0; j = j->next) 1560 1.1 jtc if (j->pgrp && j->pgrp == job) 1561 1.1 jtc return j; 1562 1.1 jtc if (ecodep) 1563 1.1 jtc *ecodep = JL_NOSUCH; 1564 1.1 jtc return (Job *) 0; 1565 1.1 jtc } 1566 1.1 jtc if (*cp != '%') { 1567 1.1 jtc if (ecodep) 1568 1.1 jtc *ecodep = JL_INVALID; 1569 1.1 jtc return (Job *) 0; 1570 1.1 jtc } 1571 1.1 jtc switch (*++cp) { 1572 1.8 mycroft case '\0': /* non-standard */ 1573 1.8 mycroft case '+': 1574 1.8 mycroft case '%': 1575 1.1 jtc if (job_list != (Job *) 0) 1576 1.1 jtc return job_list; 1577 1.1 jtc break; 1578 1.1 jtc 1579 1.8 mycroft case '-': 1580 1.1 jtc if (job_list != (Job *) 0 && job_list->next) 1581 1.1 jtc return job_list->next; 1582 1.1 jtc break; 1583 1.1 jtc 1584 1.8 mycroft case '0': case '1': case '2': case '3': case '4': 1585 1.8 mycroft case '5': case '6': case '7': case '8': case '9': 1586 1.1 jtc job = atoi(cp); 1587 1.1 jtc for (j = job_list; j != (Job *) 0; j = j->next) 1588 1.1 jtc if (j->job == job) 1589 1.1 jtc return j; 1590 1.1 jtc break; 1591 1.1 jtc 1592 1.8 mycroft case '?': /* %?string */ 1593 1.1 jtc last_match = (Job *) 0; 1594 1.1 jtc for (j = job_list; j != (Job *) 0; j = j->next) 1595 1.1 jtc for (p = j->proc_list; p != (Proc *) 0; p = p->next) 1596 1.1 jtc if (strstr(p->command, cp+1) != (char *) 0) { 1597 1.1 jtc if (last_match) { 1598 1.1 jtc if (ecodep) 1599 1.1 jtc *ecodep = JL_AMBIG; 1600 1.1 jtc return (Job *) 0; 1601 1.1 jtc } 1602 1.1 jtc last_match = j; 1603 1.1 jtc } 1604 1.1 jtc if (last_match) 1605 1.1 jtc return last_match; 1606 1.1 jtc break; 1607 1.1 jtc 1608 1.8 mycroft default: /* %string */ 1609 1.1 jtc len = strlen(cp); 1610 1.1 jtc last_match = (Job *) 0; 1611 1.1 jtc for (j = job_list; j != (Job *) 0; j = j->next) 1612 1.1 jtc if (strncmp(cp, j->proc_list->command, len) == 0) { 1613 1.1 jtc if (last_match) { 1614 1.1 jtc if (ecodep) 1615 1.1 jtc *ecodep = JL_AMBIG; 1616 1.1 jtc return (Job *) 0; 1617 1.1 jtc } 1618 1.1 jtc last_match = j; 1619 1.1 jtc } 1620 1.1 jtc if (last_match) 1621 1.1 jtc return last_match; 1622 1.1 jtc break; 1623 1.1 jtc } 1624 1.1 jtc if (ecodep) 1625 1.1 jtc *ecodep = JL_NOSUCH; 1626 1.1 jtc return (Job *) 0; 1627 1.1 jtc } 1628 1.1 jtc 1629 1.1 jtc static Job *free_jobs; 1630 1.1 jtc static Proc *free_procs; 1631 1.1 jtc 1632 1.1 jtc /* allocate a new job and fill in the job number. 1633 1.1 jtc * 1634 1.1 jtc * If jobs are compiled in then this routine expects sigchld to be blocked. 1635 1.1 jtc */ 1636 1.1 jtc static Job * 1637 1.1 jtc new_job() 1638 1.1 jtc { 1639 1.1 jtc int i; 1640 1.1 jtc Job *newj, *j; 1641 1.1 jtc 1642 1.1 jtc if (free_jobs != (Job *) 0) { 1643 1.1 jtc newj = free_jobs; 1644 1.1 jtc free_jobs = free_jobs->next; 1645 1.1 jtc } else 1646 1.1 jtc newj = (Job *) alloc(sizeof(Job), APERM); 1647 1.1 jtc 1648 1.1 jtc /* brute force method */ 1649 1.1 jtc for (i = 1; ; i++) { 1650 1.1 jtc for (j = job_list; j && j->job != i; j = j->next) 1651 1.1 jtc ; 1652 1.1 jtc if (j == (Job *) 0) 1653 1.1 jtc break; 1654 1.1 jtc } 1655 1.1 jtc newj->job = i; 1656 1.1 jtc 1657 1.1 jtc return newj; 1658 1.1 jtc } 1659 1.1 jtc 1660 1.9 wiz /* Allocate new process struct 1661 1.1 jtc * 1662 1.1 jtc * If jobs are compiled in then this routine expects sigchld to be blocked. 1663 1.1 jtc */ 1664 1.1 jtc static Proc * 1665 1.1 jtc new_proc() 1666 1.1 jtc { 1667 1.1 jtc Proc *p; 1668 1.1 jtc 1669 1.1 jtc if (free_procs != (Proc *) 0) { 1670 1.1 jtc p = free_procs; 1671 1.1 jtc free_procs = free_procs->next; 1672 1.1 jtc } else 1673 1.1 jtc p = (Proc *) alloc(sizeof(Proc), APERM); 1674 1.1 jtc 1675 1.1 jtc return p; 1676 1.1 jtc } 1677 1.1 jtc 1678 1.1 jtc /* Take job out of job_list and put old structures into free list. 1679 1.1 jtc * Keeps nzombies, last_job and async_job up to date. 1680 1.1 jtc * 1681 1.1 jtc * If jobs are compiled in then this routine expects sigchld to be blocked. 1682 1.1 jtc */ 1683 1.1 jtc static void 1684 1.1 jtc remove_job(j, where) 1685 1.1 jtc Job *j; 1686 1.1 jtc const char *where; 1687 1.1 jtc { 1688 1.1 jtc Proc *p, *tmp; 1689 1.1 jtc Job **prev, *curr; 1690 1.1 jtc 1691 1.1 jtc prev = &job_list; 1692 1.1 jtc curr = *prev; 1693 1.1 jtc for (; curr != (Job *) 0 && curr != j; prev = &curr->next, curr = *prev) 1694 1.1 jtc ; 1695 1.1 jtc if (curr != j) { 1696 1.1 jtc internal_errorf(0, "remove_job: job not found (%s)", where); 1697 1.1 jtc return; 1698 1.1 jtc } 1699 1.1 jtc *prev = curr->next; 1700 1.1 jtc 1701 1.1 jtc /* free up proc structures */ 1702 1.1 jtc for (p = j->proc_list; p != (Proc *) 0; ) { 1703 1.1 jtc tmp = p; 1704 1.1 jtc p = p->next; 1705 1.1 jtc tmp->next = free_procs; 1706 1.1 jtc free_procs = tmp; 1707 1.1 jtc } 1708 1.1 jtc 1709 1.1 jtc if ((j->flags & JF_ZOMBIE) && j->ppid == procpid) 1710 1.1 jtc --nzombie; 1711 1.1 jtc j->next = free_jobs; 1712 1.1 jtc free_jobs = j; 1713 1.1 jtc 1714 1.1 jtc if (j == last_job) 1715 1.1 jtc last_job = (Job *) 0; 1716 1.1 jtc if (j == async_job) 1717 1.1 jtc async_job = (Job *) 0; 1718 1.1 jtc } 1719 1.1 jtc 1720 1.1 jtc /* put j in a particular location (taking it out job_list if it is there 1721 1.1 jtc * already) 1722 1.1 jtc * 1723 1.1 jtc * If jobs are compiled in then this routine expects sigchld to be blocked. 1724 1.1 jtc */ 1725 1.1 jtc static void 1726 1.1 jtc put_job(j, where) 1727 1.1 jtc Job *j; 1728 1.1 jtc int where; 1729 1.1 jtc { 1730 1.1 jtc Job **prev, *curr; 1731 1.1 jtc 1732 1.1 jtc /* Remove job from list (if there) */ 1733 1.1 jtc prev = &job_list; 1734 1.1 jtc curr = job_list; 1735 1.1 jtc for (; curr && curr != j; prev = &curr->next, curr = *prev) 1736 1.1 jtc ; 1737 1.1 jtc if (curr == j) 1738 1.1 jtc *prev = curr->next; 1739 1.1 jtc 1740 1.1 jtc switch (where) { 1741 1.1 jtc case PJ_ON_FRONT: 1742 1.1 jtc j->next = job_list; 1743 1.1 jtc job_list = j; 1744 1.1 jtc break; 1745 1.1 jtc 1746 1.1 jtc case PJ_PAST_STOPPED: 1747 1.1 jtc prev = &job_list; 1748 1.1 jtc curr = job_list; 1749 1.1 jtc for (; curr && curr->state == PSTOPPED; prev = &curr->next, 1750 1.1 jtc curr = *prev) 1751 1.1 jtc ; 1752 1.1 jtc j->next = curr; 1753 1.1 jtc *prev = j; 1754 1.1 jtc break; 1755 1.1 jtc } 1756 1.1 jtc } 1757 1.1 jtc 1758 1.1 jtc /* nuke a job (called when unable to start full job). 1759 1.1 jtc * 1760 1.1 jtc * If jobs are compiled in then this routine expects sigchld to be blocked. 1761 1.1 jtc */ 1762 1.6 christos static int 1763 1.6 christos kill_job(j, sig) 1764 1.1 jtc Job *j; 1765 1.6 christos int sig; 1766 1.1 jtc { 1767 1.1 jtc Proc *p; 1768 1.6 christos int rval = 0; 1769 1.1 jtc 1770 1.1 jtc for (p = j->proc_list; p != (Proc *) 0; p = p->next) 1771 1.1 jtc if (p->pid != 0) 1772 1.6 christos if (kill(p->pid, sig) < 0) 1773 1.6 christos rval = -1; 1774 1.6 christos return rval; 1775 1.1 jtc } 1776