PageRenderTime 82ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/contrib/tcsh/sh.proc.c

https://bitbucket.org/freebsd/freebsd-head/
C | 2028 lines | 1567 code | 144 blank | 317 comment | 526 complexity | d101d4b54122f9c3a33bf1326e3d4e52 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, BSD-3-Clause, LGPL-2.0, LGPL-2.1, BSD-2-Clause, 0BSD, JSON, AGPL-1.0, GPL-2.0
  1. /* $Header: /p/tcsh/cvsroot/tcsh/sh.proc.c,v 3.121 2012/01/25 15:34:41 christos Exp $ */
  2. /*
  3. * sh.proc.c: Job manipulations
  4. */
  5. /*-
  6. * Copyright (c) 1980, 1991 The Regents of the University of California.
  7. * All rights reserved.
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted provided that the following conditions
  11. * are met:
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in the
  16. * documentation and/or other materials provided with the distribution.
  17. * 3. Neither the name of the University nor the names of its contributors
  18. * may be used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31. * SUCH DAMAGE.
  32. */
  33. #include "sh.h"
  34. RCSID("$tcsh: sh.proc.c,v 3.121 2012/01/25 15:34:41 christos Exp $")
  35. #include "ed.h"
  36. #include "tc.h"
  37. #include "tc.wait.h"
  38. #ifdef WINNT_NATIVE
  39. #undef POSIX
  40. #define POSIX
  41. #endif /* WINNT_NATIVE */
  42. #ifdef aiws
  43. # undef HZ
  44. # define HZ 16
  45. #endif /* aiws */
  46. #if defined(_BSD) || (defined(IRIS4D) && __STDC__) || defined(__lucid) || defined(__linux__) || defined(__GNU__) || defined(__GLIBC__)
  47. # if !defined(__ANDROID__)
  48. # define BSDWAIT
  49. # endif
  50. #endif /* _BSD || (IRIS4D && __STDC__) || __lucid || glibc */
  51. #ifndef WTERMSIG
  52. # define WTERMSIG(w) (((union wait *) &(w))->w_termsig)
  53. # ifndef BSDWAIT
  54. # define BSDWAIT
  55. # endif /* !BSDWAIT */
  56. #endif /* !WTERMSIG */
  57. #ifndef WEXITSTATUS
  58. # define WEXITSTATUS(w) (((union wait *) &(w))->w_retcode)
  59. #endif /* !WEXITSTATUS */
  60. #ifndef WSTOPSIG
  61. # define WSTOPSIG(w) (((union wait *) &(w))->w_stopsig)
  62. #endif /* !WSTOPSIG */
  63. #ifdef __osf__
  64. # ifndef WCOREDUMP
  65. # define WCOREDUMP(x) (_W_INT(x) & WCOREFLAG)
  66. # endif
  67. #endif
  68. #ifndef WCOREDUMP
  69. # ifdef BSDWAIT
  70. # define WCOREDUMP(w) (((union wait *) &(w))->w_coredump)
  71. # else /* !BSDWAIT */
  72. # define WCOREDUMP(w) ((w) & 0200)
  73. # endif /* !BSDWAIT */
  74. #endif /* !WCOREDUMP */
  75. #ifndef JOBDEBUG
  76. # define jobdebug_xprintf(x) (void)0
  77. # define jobdebug_flush() (void)0
  78. #else
  79. # define jobdebug_xprintf(s) xprintf s
  80. # define jobdebug_flush() flush()
  81. #endif
  82. /*
  83. * C Shell - functions that manage processes, handling hanging, termination
  84. */
  85. #define BIGINDEX 9 /* largest desirable job index */
  86. #ifdef BSDTIMES
  87. # ifdef convex
  88. /* use 'cvxrusage' to get parallel statistics */
  89. static struct cvxrusage zru = {{0L, 0L}, {0L, 0L}, 0L, 0L, 0L, 0L,
  90. 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L,
  91. {0L, 0L}, 0LL, 0LL, 0LL, 0LL, 0L, 0L, 0L,
  92. 0LL, 0LL, {0L, 0L, 0L, 0L, 0L}};
  93. # else
  94. static struct rusage zru;
  95. # endif /* convex */
  96. #else /* !BSDTIMES */
  97. # ifdef _SEQUENT_
  98. static struct process_stats zru = {{0L, 0L}, {0L, 0L}, 0, 0, 0, 0, 0, 0, 0,
  99. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  100. # else /* !_SEQUENT_ */
  101. # ifdef _SX
  102. static struct tms zru = {0, 0, 0, 0}, lru = {0, 0, 0, 0};
  103. # else /* !_SX */
  104. static struct tms zru = {0L, 0L, 0L, 0L}, lru = {0L, 0L, 0L, 0L};
  105. # endif /* !_SX */
  106. # endif /* !_SEQUENT_ */
  107. #endif /* !BSDTIMES */
  108. #ifndef BSDTIMES
  109. static int timesdone; /* shtimes buffer full ? */
  110. #endif /* BSDTIMES */
  111. #ifndef RUSAGE_CHILDREN
  112. # define RUSAGE_CHILDREN -1
  113. #endif /* RUSAGE_CHILDREN */
  114. static void pflushall (void);
  115. static void pflush (struct process *);
  116. static void pfree (struct process *);
  117. static void pclrcurr (struct process *);
  118. static void morecommand (size_t);
  119. static void padd (struct command *);
  120. static int pprint (struct process *, int);
  121. static void ptprint (struct process *);
  122. static void pads (Char *);
  123. static void pkill (Char **, int);
  124. static struct process *pgetcurr (struct process *);
  125. static void okpcntl (void);
  126. static void setttypgrp (int);
  127. /*
  128. * pchild - call queued by the SIGCHLD signal
  129. * indicating that at least one child has terminated or stopped
  130. * thus at least one wait system call will definitely return a
  131. * childs status. Top level routines (like pwait) must be sure
  132. * to mask interrupts when playing with the proclist data structures!
  133. */
  134. void
  135. pchild(void)
  136. {
  137. struct process *pp;
  138. struct process *fp;
  139. pid_t pid;
  140. #ifdef BSDWAIT
  141. union wait w;
  142. #else /* !BSDWAIT */
  143. int w;
  144. #endif /* !BSDWAIT */
  145. int jobflags;
  146. #ifdef BSDTIMES
  147. struct sysrusage ru;
  148. #else /* !BSDTIMES */
  149. # ifdef _SEQUENT_
  150. struct process_stats ru;
  151. struct process_stats cpst1, cpst2;
  152. timeval_t tv;
  153. # else /* !_SEQUENT_ */
  154. struct tms proctimes;
  155. if (!timesdone) {
  156. timesdone++;
  157. (void) times(&shtimes);
  158. }
  159. # endif /* !_SEQUENT_ */
  160. #endif /* !BSDTIMES */
  161. jobdebug_xprintf(("pchild()\n"));
  162. loop:
  163. jobdebug_xprintf(("Waiting...\n"));
  164. jobdebug_flush();
  165. errno = 0; /* reset, just in case */
  166. #ifndef WINNT_NATIVE
  167. # ifdef BSDJOBS
  168. # ifdef BSDTIMES
  169. # ifdef convex
  170. /* use 'cvxwait' to get parallel statistics */
  171. pid = cvxwait(&w,
  172. (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), &ru);
  173. # else
  174. /* both a wait3 and rusage */
  175. # if !defined(BSDWAIT) || defined(NeXT) || defined(MACH) || defined(__linux__) || defined(__GNU__) || defined(__GLIBC__) || (defined(IRIS4D) && SYSVREL <= 3) || defined(__lucid) || defined(__osf__)
  176. pid = wait3(&w,
  177. (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), &ru);
  178. # else /* BSDWAIT */
  179. pid = wait3(&w.w_status,
  180. (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), &ru);
  181. # endif /* BSDWAIT */
  182. # endif /* convex */
  183. # else /* !BSDTIMES */
  184. # ifdef _SEQUENT_
  185. (void) get_process_stats(&tv, PS_SELF, 0, &cpst1);
  186. pid = waitpid(-1, &w,
  187. (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG));
  188. (void) get_process_stats(&tv, PS_SELF, 0, &cpst2);
  189. pr_stat_sub(&cpst2, &cpst1, &ru);
  190. # else /* !_SEQUENT_ */
  191. # ifndef POSIX
  192. /* we have a wait3, but no rusage stuff */
  193. pid = wait3(&w.w_status,
  194. (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), 0);
  195. # else /* POSIX */
  196. pid = waitpid(-1, &w,
  197. (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG));
  198. # endif /* POSIX */
  199. # endif /* !_SEQUENT_ */
  200. # endif /* !BSDTIMES */
  201. # else /* !BSDJOBS */
  202. # ifdef BSDTIMES
  203. # define HAVEwait3
  204. /* both a wait3 and rusage */
  205. # ifdef hpux
  206. pid = wait3(&w.w_status, WNOHANG, 0);
  207. # else /* !hpux */
  208. # ifndef BSDWAIT
  209. pid = wait3(&w, WNOHANG, &ru);
  210. # else
  211. pid = wait3(&w.w_status, WNOHANG, &ru);
  212. # endif /* BSDWAIT */
  213. # endif /* !hpux */
  214. # else /* !BSDTIMES */
  215. # ifdef ODT /* For Sco Unix 3.2.0 or ODT 1.0 */
  216. # define HAVEwait3
  217. pid = waitpid(-1, &w,
  218. (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG));
  219. # endif /* ODT */
  220. # if defined(aiws) || defined(uts)
  221. # define HAVEwait3
  222. pid = wait3(&w.w_status,
  223. (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), 0);
  224. # endif /* aiws || uts */
  225. # ifndef HAVEwait3
  226. # ifndef BSDWAIT
  227. /* no wait3, therefore no rusage */
  228. /* on Sys V, this may hang. I hope it's not going to be a problem */
  229. pid = wait(&w);
  230. # else /* BSDWAIT */
  231. /*
  232. * XXX: for greater than 3 we should use waitpid().
  233. * but then again, SVR4 falls into the POSIX/BSDJOBS category.
  234. */
  235. pid = wait(&w.w_status);
  236. # endif /* BSDWAIT */
  237. # endif /* !HAVEwait3 */
  238. # endif /* !BSDTIMES */
  239. # endif /* !BSDJOBS */
  240. #else /* WINNT_NATIVE */
  241. pid = waitpid(-1, &w,
  242. (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG));
  243. #endif /* WINNT_NATIVE */
  244. jobdebug_xprintf(("parent %d pid %d, retval %x termsig %x retcode %x\n",
  245. (int)getpid(), (int)pid, w, WTERMSIG(w),
  246. WEXITSTATUS(w)));
  247. jobdebug_flush();
  248. if ((pid == 0) || (pid == -1)) {
  249. (void)handle_pending_signals();
  250. jobdebug_xprintf(("errno == %d\n", errno));
  251. if (errno == EINTR)
  252. goto loop;
  253. goto end;
  254. }
  255. for (pp = proclist.p_next; pp != NULL; pp = pp->p_next)
  256. if (pid == pp->p_procid)
  257. goto found;
  258. #if !defined(BSDJOBS) && !defined(WINNT_NATIVE)
  259. /* this should never have happened */
  260. stderror(ERR_SYNC, pid);
  261. xexit(0);
  262. #else /* BSDJOBS || WINNT_NATIVE */
  263. goto loop;
  264. #endif /* !BSDJOBS && !WINNT_NATIVE */
  265. found:
  266. pp->p_flags &= ~(PRUNNING | PSTOPPED | PREPORTED);
  267. if (WIFSTOPPED(w)) {
  268. pp->p_flags |= PSTOPPED;
  269. pp->p_reason = WSTOPSIG(w);
  270. }
  271. else {
  272. if (pp->p_flags & (PTIME | PPTIME) || adrof(STRtime))
  273. #ifndef BSDTIMES
  274. # ifdef _SEQUENT_
  275. (void) get_process_stats(&pp->p_etime, PS_SELF, NULL, NULL);
  276. # else /* !_SEQUENT_ */
  277. pp->p_etime = times(&proctimes);
  278. # endif /* !_SEQUENT_ */
  279. #else /* BSDTIMES */
  280. (void) gettimeofday(&pp->p_etime, NULL);
  281. #endif /* BSDTIMES */
  282. #if defined(BSDTIMES) || defined(_SEQUENT_)
  283. pp->p_rusage = ru;
  284. #else /* !BSDTIMES && !_SEQUENT_ */
  285. (void) times(&proctimes);
  286. pp->p_utime = proctimes.tms_cutime - shtimes.tms_cutime;
  287. pp->p_stime = proctimes.tms_cstime - shtimes.tms_cstime;
  288. shtimes = proctimes;
  289. #endif /* !BSDTIMES && !_SEQUENT_ */
  290. if (WIFSIGNALED(w)) {
  291. if (WTERMSIG(w) == SIGINT)
  292. pp->p_flags |= PINTERRUPTED;
  293. else
  294. pp->p_flags |= PSIGNALED;
  295. if (WCOREDUMP(w))
  296. pp->p_flags |= PDUMPED;
  297. pp->p_reason = WTERMSIG(w);
  298. }
  299. else {
  300. pp->p_reason = WEXITSTATUS(w);
  301. if (pp->p_reason != 0)
  302. pp->p_flags |= PAEXITED;
  303. else
  304. pp->p_flags |= PNEXITED;
  305. }
  306. }
  307. jobflags = 0;
  308. fp = pp;
  309. do {
  310. if ((fp->p_flags & (PPTIME | PRUNNING | PSTOPPED)) == 0 &&
  311. !child && adrof(STRtime) &&
  312. #ifdef BSDTIMES
  313. fp->p_rusage.ru_utime.tv_sec + fp->p_rusage.ru_stime.tv_sec
  314. #else /* !BSDTIMES */
  315. # ifdef _SEQUENT_
  316. fp->p_rusage.ps_utime.tv_sec + fp->p_rusage.ps_stime.tv_sec
  317. # else /* !_SEQUENT_ */
  318. # ifndef POSIX
  319. (fp->p_utime + fp->p_stime) / HZ
  320. # else /* POSIX */
  321. (fp->p_utime + fp->p_stime) / clk_tck
  322. # endif /* POSIX */
  323. # endif /* !_SEQUENT_ */
  324. #endif /* !BSDTIMES */
  325. >= atoi(short2str(varval(STRtime))))
  326. fp->p_flags |= PTIME;
  327. jobflags |= fp->p_flags;
  328. } while ((fp = fp->p_friends) != pp);
  329. pp->p_flags &= ~PFOREGND;
  330. if (pp == pp->p_friends && (pp->p_flags & PPTIME)) {
  331. pp->p_flags &= ~PPTIME;
  332. pp->p_flags |= PTIME;
  333. }
  334. if ((jobflags & (PRUNNING | PREPORTED)) == 0) {
  335. fp = pp;
  336. do {
  337. if (fp->p_flags & PSTOPPED)
  338. fp->p_flags |= PREPORTED;
  339. } while ((fp = fp->p_friends) != pp);
  340. while (fp->p_procid != fp->p_jobid)
  341. fp = fp->p_friends;
  342. if (jobflags & PSTOPPED) {
  343. if (pcurrent && pcurrent != fp)
  344. pprevious = pcurrent;
  345. pcurrent = fp;
  346. }
  347. else
  348. pclrcurr(fp);
  349. if (jobflags & PFOREGND) {
  350. if (!(jobflags & (PSIGNALED | PSTOPPED | PPTIME) ||
  351. #ifdef notdef
  352. jobflags & PAEXITED ||
  353. #endif /* notdef */
  354. fp->p_cwd == NULL ||
  355. !eq(dcwd->di_name, fp->p_cwd->di_name))) {
  356. /* PWP: print a newline after ^C */
  357. if (jobflags & PINTERRUPTED) {
  358. xputchar('\r' | QUOTE);
  359. xputchar('\n');
  360. }
  361. #ifdef notdef
  362. else if ((jobflags & (PTIME|PSTOPPED)) == PTIME)
  363. ptprint(fp);
  364. #endif /* notdef */
  365. }
  366. }
  367. else {
  368. if (jobflags & PNOTIFY || adrof(STRnotify)) {
  369. xputchar('\r' | QUOTE);
  370. xputchar('\n');
  371. (void) pprint(pp, NUMBER | NAME | REASON);
  372. if ((jobflags & PSTOPPED) == 0)
  373. pflush(pp);
  374. if (GettingInput) {
  375. errno = 0;
  376. (void) Rawmode();
  377. #ifdef notdef
  378. /*
  379. * don't really want to do that, because it
  380. * will erase our message in case of multi-line
  381. * input
  382. */
  383. ClearLines();
  384. #endif /* notdef */
  385. ClearDisp();
  386. Refresh();
  387. }
  388. }
  389. else {
  390. fp->p_flags |= PNEEDNOTE;
  391. neednote = 1;
  392. }
  393. }
  394. }
  395. #if defined(BSDJOBS) || defined(HAVEwait3) ||defined(WINNT_NATIVE)
  396. goto loop;
  397. #endif /* BSDJOBS || HAVEwait3 */
  398. end:
  399. ;
  400. }
  401. void
  402. pnote(void)
  403. {
  404. struct process *pp;
  405. int flags;
  406. neednote = 0;
  407. for (pp = proclist.p_next; pp != NULL; pp = pp->p_next) {
  408. if (pp->p_flags & PNEEDNOTE) {
  409. pchild_disabled++;
  410. cleanup_push(&pchild_disabled, disabled_cleanup);
  411. pp->p_flags &= ~PNEEDNOTE;
  412. flags = pprint(pp, NUMBER | NAME | REASON);
  413. if ((flags & (PRUNNING | PSTOPPED)) == 0)
  414. pflush(pp);
  415. cleanup_until(&pchild_disabled);
  416. }
  417. }
  418. }
  419. static void
  420. pfree(struct process *pp)
  421. {
  422. xfree(pp->p_command);
  423. if (pp->p_cwd && --pp->p_cwd->di_count == 0)
  424. if (pp->p_cwd->di_next == 0)
  425. dfree(pp->p_cwd);
  426. xfree(pp);
  427. }
  428. /*
  429. * pwait - wait for current job to terminate, maintaining integrity
  430. * of current and previous job indicators.
  431. */
  432. void
  433. pwait(void)
  434. {
  435. struct process *fp, *pp;
  436. /*
  437. * Here's where dead procs get flushed.
  438. */
  439. for (pp = (fp = &proclist)->p_next; pp != NULL; pp = (fp = pp)->p_next)
  440. if (pp->p_procid == 0) {
  441. fp->p_next = pp->p_next;
  442. pfree(pp);
  443. pp = fp;
  444. }
  445. pjwait(pcurrjob);
  446. }
  447. /*
  448. * pjwait - wait for a job to finish or become stopped
  449. * It is assumed to be in the foreground state (PFOREGND)
  450. */
  451. void
  452. pjwait(struct process *pp)
  453. {
  454. struct process *fp;
  455. int jobflags, reason;
  456. sigset_t oset, set, pause_mask;
  457. Char *reason_str;
  458. while (pp->p_procid != pp->p_jobid)
  459. pp = pp->p_friends;
  460. fp = pp;
  461. do {
  462. if ((fp->p_flags & (PFOREGND | PRUNNING)) == PRUNNING)
  463. xprintf("%s", CGETS(17, 1, "BUG: waiting for background job!\n"));
  464. } while ((fp = fp->p_friends) != pp);
  465. /*
  466. * Now keep pausing as long as we are not interrupted (SIGINT), and the
  467. * target process, or any of its friends, are running
  468. */
  469. fp = pp;
  470. sigemptyset(&set);
  471. sigaddset(&set, SIGINT);
  472. sigaddset(&set, SIGCHLD);
  473. (void)sigprocmask(SIG_BLOCK, &set, &oset);
  474. cleanup_push(&oset, sigprocmask_cleanup);
  475. pause_mask = oset;
  476. sigdelset(&pause_mask, SIGCHLD);
  477. for (;;) {
  478. (void)handle_pending_signals();
  479. jobflags = 0;
  480. do
  481. jobflags |= fp->p_flags;
  482. while ((fp = (fp->p_friends)) != pp);
  483. if ((jobflags & PRUNNING) == 0)
  484. break;
  485. jobdebug_xprintf(("%d starting to sigsuspend for SIGCHLD on %d\n",
  486. getpid(), fp->p_procid));
  487. sigsuspend(&pause_mask);
  488. }
  489. cleanup_until(&oset);
  490. jobdebug_xprintf(("%d returned from sigsuspend loop\n", getpid()));
  491. #ifdef BSDJOBS
  492. if (tpgrp > 0) /* get tty back */
  493. (void) tcsetpgrp(FSHTTY, tpgrp);
  494. #endif /* BSDJOBS */
  495. if ((jobflags & (PSIGNALED | PSTOPPED | PTIME)) ||
  496. fp->p_cwd == NULL || !eq(dcwd->di_name, fp->p_cwd->di_name)) {
  497. if (jobflags & PSTOPPED) {
  498. xputchar('\n');
  499. if (adrof(STRlistjobs)) {
  500. Char *jobcommand[3];
  501. jobcommand[0] = STRjobs;
  502. if (eq(varval(STRlistjobs), STRlong))
  503. jobcommand[1] = STRml;
  504. else
  505. jobcommand[1] = NULL;
  506. jobcommand[2] = NULL;
  507. dojobs(jobcommand, NULL);
  508. (void) pprint(pp, SHELLDIR);
  509. }
  510. else
  511. (void) pprint(pp, AREASON | SHELLDIR);
  512. }
  513. else
  514. (void) pprint(pp, AREASON | SHELLDIR);
  515. }
  516. if ((jobflags & (PINTERRUPTED | PSTOPPED)) && setintr &&
  517. (!gointr || !eq(gointr, STRminus))) {
  518. if ((jobflags & PSTOPPED) == 0)
  519. pflush(pp);
  520. pintr1(0);
  521. /* NOTREACHED */
  522. }
  523. reason = 0;
  524. fp = pp;
  525. do {
  526. /* In case of pipelines only the result of the last
  527. * command should be taken in account */
  528. if (!anyerror && !(fp->p_flags & PBRACE)
  529. && ((fp->p_flags & PPOU) || (fp->p_flags & PBACKQ)))
  530. continue;
  531. if (fp->p_reason)
  532. reason = fp->p_flags & (PSIGNALED | PINTERRUPTED) ?
  533. fp->p_reason | META : fp->p_reason;
  534. } while ((fp = fp->p_friends) != pp);
  535. /*
  536. * Don't report on backquoted jobs, cause it will mess up
  537. * their output.
  538. */
  539. if ((reason != 0) && (adrof(STRprintexitvalue)) &&
  540. (pp->p_flags & PBACKQ) == 0)
  541. xprintf(CGETS(17, 2, "Exit %d\n"), reason);
  542. reason_str = putn((tcsh_number_t)reason);
  543. cleanup_push(reason_str, xfree);
  544. setv(STRstatus, reason_str, VAR_READWRITE);
  545. cleanup_ignore(reason_str);
  546. cleanup_until(reason_str);
  547. if (reason && exiterr)
  548. exitstat();
  549. pflush(pp);
  550. }
  551. /*
  552. * dowait - wait for all processes to finish
  553. */
  554. /*ARGSUSED*/
  555. void
  556. dowait(Char **v, struct command *c)
  557. {
  558. struct process *pp;
  559. sigset_t pause_mask;
  560. int opintr_disabled, gotsig;
  561. USE(c);
  562. USE(v);
  563. pjobs++;
  564. sigprocmask(SIG_BLOCK, NULL, &pause_mask);
  565. sigdelset(&pause_mask, SIGCHLD);
  566. if (setintr)
  567. sigdelset(&pause_mask, SIGINT);
  568. loop:
  569. for (pp = proclist.p_next; pp; pp = pp->p_next)
  570. if (pp->p_procid && /* pp->p_procid == pp->p_jobid && */
  571. pp->p_flags & PRUNNING) {
  572. (void)handle_pending_signals();
  573. sigsuspend(&pause_mask);
  574. opintr_disabled = pintr_disabled;
  575. pintr_disabled = 0;
  576. gotsig = handle_pending_signals();
  577. pintr_disabled = opintr_disabled;
  578. if (gotsig)
  579. break;
  580. goto loop;
  581. }
  582. pjobs = 0;
  583. }
  584. /*
  585. * pflushall - flush all jobs from list (e.g. at fork())
  586. */
  587. static void
  588. pflushall(void)
  589. {
  590. struct process *pp;
  591. for (pp = proclist.p_next; pp != NULL; pp = pp->p_next)
  592. if (pp->p_procid)
  593. pflush(pp);
  594. }
  595. /*
  596. * pflush - flag all process structures in the same job as the
  597. * the argument process for deletion. The actual free of the
  598. * space is not done here since pflush is called at interrupt level.
  599. */
  600. static void
  601. pflush(struct process *pp)
  602. {
  603. struct process *np;
  604. int idx;
  605. if (pp->p_procid == 0) {
  606. xprintf("%s", CGETS(17, 3, "BUG: process flushed twice"));
  607. return;
  608. }
  609. while (pp->p_procid != pp->p_jobid)
  610. pp = pp->p_friends;
  611. pclrcurr(pp);
  612. if (pp == pcurrjob)
  613. pcurrjob = 0;
  614. idx = pp->p_index;
  615. np = pp;
  616. do {
  617. np->p_index = np->p_procid = 0;
  618. np->p_flags &= ~PNEEDNOTE;
  619. } while ((np = np->p_friends) != pp);
  620. if (idx == pmaxindex) {
  621. for (np = proclist.p_next, idx = 0; np; np = np->p_next)
  622. if (np->p_index > idx)
  623. idx = np->p_index;
  624. pmaxindex = idx;
  625. }
  626. }
  627. /*
  628. * pclrcurr - make sure the given job is not the current or previous job;
  629. * pp MUST be the job leader
  630. */
  631. static void
  632. pclrcurr(struct process *pp)
  633. {
  634. if (pp == pcurrent) {
  635. if (pprevious != NULL) {
  636. pcurrent = pprevious;
  637. pprevious = pgetcurr(pp);
  638. }
  639. else {
  640. pcurrent = pgetcurr(pp);
  641. pprevious = pgetcurr(pp);
  642. }
  643. }
  644. else if (pp == pprevious)
  645. pprevious = pgetcurr(pp);
  646. }
  647. /* +4 here is 1 for '\0', 1 ea for << >& >> */
  648. static Char *cmdstr;
  649. static size_t cmdmax;
  650. static size_t cmdlen;
  651. static Char *cmdp;
  652. #define CMD_INIT 1024
  653. #define CMD_INCR 64
  654. static void
  655. morecommand(size_t s)
  656. {
  657. Char *ncmdstr;
  658. ptrdiff_t d;
  659. cmdmax += s;
  660. ncmdstr = xrealloc(cmdstr, cmdmax * sizeof(*cmdstr));
  661. d = ncmdstr - cmdstr;
  662. cmdstr = ncmdstr;
  663. cmdp += d;
  664. }
  665. /* GrP
  666. * unparse - Export padd() functionality
  667. */
  668. Char *
  669. unparse(struct command *t)
  670. {
  671. if (cmdmax == 0)
  672. morecommand(CMD_INIT);
  673. cmdp = cmdstr;
  674. cmdlen = 0;
  675. padd(t);
  676. *cmdp++ = '\0';
  677. return Strsave(cmdstr);
  678. }
  679. /*
  680. * palloc - allocate a process structure and fill it up.
  681. * an important assumption is made that the process is running.
  682. */
  683. void
  684. palloc(pid_t pid, struct command *t)
  685. {
  686. struct process *pp;
  687. int i;
  688. pp = xcalloc(1, sizeof(struct process));
  689. pp->p_procid = pid;
  690. pp->p_parentid = shpgrp;
  691. pp->p_flags = ((t->t_dflg & F_AMPERSAND) ? 0 : PFOREGND) | PRUNNING;
  692. if (t->t_dflg & F_TIME)
  693. pp->p_flags |= PPTIME;
  694. if (t->t_dflg & F_BACKQ)
  695. pp->p_flags |= PBACKQ;
  696. if (t->t_dflg & F_HUP)
  697. pp->p_flags |= PHUP;
  698. if (t->t_dcom && t->t_dcom[0] && (*t->t_dcom[0] == '{'))
  699. pp->p_flags |= PBRACE;
  700. if (cmdmax == 0)
  701. morecommand(CMD_INIT);
  702. cmdp = cmdstr;
  703. cmdlen = 0;
  704. padd(t);
  705. *cmdp++ = 0;
  706. if (t->t_dflg & F_PIPEOUT) {
  707. pp->p_flags |= PPOU;
  708. if (t->t_dflg & F_STDERR)
  709. pp->p_flags |= PDIAG;
  710. }
  711. pp->p_command = Strsave(cmdstr);
  712. if (pcurrjob) {
  713. struct process *fp;
  714. /* careful here with interrupt level */
  715. pp->p_cwd = 0;
  716. pp->p_index = pcurrjob->p_index;
  717. pp->p_friends = pcurrjob;
  718. pp->p_jobid = pcurrjob->p_procid;
  719. for (fp = pcurrjob; fp->p_friends != pcurrjob; fp = fp->p_friends)
  720. continue;
  721. fp->p_friends = pp;
  722. }
  723. else {
  724. pcurrjob = pp;
  725. pp->p_jobid = pid;
  726. pp->p_friends = pp;
  727. pp->p_cwd = dcwd;
  728. dcwd->di_count++;
  729. if (pmaxindex < BIGINDEX)
  730. pp->p_index = ++pmaxindex;
  731. else {
  732. struct process *np;
  733. for (i = 1;; i++) {
  734. for (np = proclist.p_next; np; np = np->p_next)
  735. if (np->p_index == i)
  736. goto tryagain;
  737. pp->p_index = i;
  738. if (i > pmaxindex)
  739. pmaxindex = i;
  740. break;
  741. tryagain:;
  742. }
  743. }
  744. if (pcurrent == NULL)
  745. pcurrent = pp;
  746. else if (pprevious == NULL)
  747. pprevious = pp;
  748. }
  749. pp->p_next = proclist.p_next;
  750. proclist.p_next = pp;
  751. #ifdef BSDTIMES
  752. (void) gettimeofday(&pp->p_btime, NULL);
  753. #else /* !BSDTIMES */
  754. # ifdef _SEQUENT_
  755. (void) get_process_stats(&pp->p_btime, PS_SELF, NULL, NULL);
  756. # else /* !_SEQUENT_ */
  757. {
  758. struct tms tmptimes;
  759. pp->p_btime = times(&tmptimes);
  760. }
  761. # endif /* !_SEQUENT_ */
  762. #endif /* !BSDTIMES */
  763. }
  764. static void
  765. padd(struct command *t)
  766. {
  767. Char **argp;
  768. if (t == 0)
  769. return;
  770. switch (t->t_dtyp) {
  771. case NODE_PAREN:
  772. pads(STRLparensp);
  773. padd(t->t_dspr);
  774. pads(STRspRparen);
  775. break;
  776. case NODE_COMMAND:
  777. for (argp = t->t_dcom; *argp; argp++) {
  778. pads(*argp);
  779. if (argp[1])
  780. pads(STRspace);
  781. }
  782. break;
  783. case NODE_OR:
  784. case NODE_AND:
  785. case NODE_PIPE:
  786. case NODE_LIST:
  787. padd(t->t_dcar);
  788. switch (t->t_dtyp) {
  789. case NODE_OR:
  790. pads(STRspor2sp);
  791. break;
  792. case NODE_AND:
  793. pads(STRspand2sp);
  794. break;
  795. case NODE_PIPE:
  796. pads(STRsporsp);
  797. break;
  798. case NODE_LIST:
  799. pads(STRsemisp);
  800. break;
  801. default:
  802. break;
  803. }
  804. padd(t->t_dcdr);
  805. return;
  806. default:
  807. break;
  808. }
  809. if ((t->t_dflg & F_PIPEIN) == 0 && t->t_dlef) {
  810. pads((t->t_dflg & F_READ) ? STRspLarrow2sp : STRspLarrowsp);
  811. pads(t->t_dlef);
  812. }
  813. if ((t->t_dflg & F_PIPEOUT) == 0 && t->t_drit) {
  814. pads((t->t_dflg & F_APPEND) ? STRspRarrow2 : STRspRarrow);
  815. if (t->t_dflg & F_STDERR)
  816. pads(STRand);
  817. pads(STRspace);
  818. pads(t->t_drit);
  819. }
  820. }
  821. static void
  822. pads(Char *cp)
  823. {
  824. size_t i, len;
  825. /*
  826. * Avoid the Quoted Space alias hack! Reported by:
  827. * sam@john-bigboote.ICS.UCI.EDU (Sam Horrocks)
  828. */
  829. if (cp[0] == STRQNULL[0])
  830. cp++;
  831. i = Strlen(cp);
  832. len = cmdlen + i + CMD_INCR;
  833. if (len >= cmdmax)
  834. morecommand(len);
  835. (void) Strcpy(cmdp, cp);
  836. cmdp += i;
  837. cmdlen += i;
  838. }
  839. /*
  840. * psavejob - temporarily save the current job on a one level stack
  841. * so another job can be created. Used for { } in exp6
  842. * and `` in globbing.
  843. */
  844. void
  845. psavejob(void)
  846. {
  847. pholdjob = pcurrjob;
  848. pcurrjob = NULL;
  849. }
  850. void
  851. psavejob_cleanup(void *dummy)
  852. {
  853. USE(dummy);
  854. pcurrjob = pholdjob;
  855. pholdjob = NULL;
  856. }
  857. /*
  858. * pendjob - indicate that a job (set of commands) has been completed
  859. * or is about to begin.
  860. */
  861. void
  862. pendjob(void)
  863. {
  864. struct process *pp, *tp;
  865. if (pcurrjob && (pcurrjob->p_flags & (PFOREGND | PSTOPPED)) == 0) {
  866. pp = pcurrjob;
  867. pcurrjob = NULL;
  868. while (pp->p_procid != pp->p_jobid)
  869. pp = pp->p_friends;
  870. xprintf("[%d]", pp->p_index);
  871. tp = pp;
  872. do {
  873. xprintf(" %d", pp->p_procid);
  874. pp = pp->p_friends;
  875. } while (pp != tp);
  876. xputchar('\n');
  877. }
  878. pholdjob = pcurrjob = 0;
  879. }
  880. /*
  881. * pprint - print a job
  882. */
  883. /*
  884. * Hacks have been added for SVR4 to deal with pipe's being spawned in
  885. * reverse order
  886. *
  887. * David Dawes (dawes@physics.su.oz.au) Oct 1991
  888. */
  889. static int
  890. pprint(struct process *pp, int flag)
  891. {
  892. int status, reason;
  893. struct process *tp;
  894. int jobflags, pstatus, pcond;
  895. const char *format;
  896. #ifdef BACKPIPE
  897. struct process *pipehead = NULL, *pipetail = NULL, *pmarker = NULL;
  898. int inpipe = 0;
  899. #endif /* BACKPIPE */
  900. while (pp->p_procid != pp->p_jobid)
  901. pp = pp->p_friends;
  902. if (pp == pp->p_friends && (pp->p_flags & PPTIME)) {
  903. pp->p_flags &= ~PPTIME;
  904. pp->p_flags |= PTIME;
  905. }
  906. tp = pp;
  907. status = reason = -1;
  908. jobflags = 0;
  909. do {
  910. #ifdef BACKPIPE
  911. /*
  912. * The pipeline is reversed, so locate the real head of the pipeline
  913. * if pp is at the tail of a pipe (and not already in a pipeline)
  914. */
  915. if ((pp->p_friends->p_flags & PPOU) && !inpipe && (flag & NAME)) {
  916. inpipe = 1;
  917. pipetail = pp;
  918. do
  919. pp = pp->p_friends;
  920. while (pp->p_friends->p_flags & PPOU);
  921. pipehead = pp;
  922. pmarker = pp;
  923. /*
  924. * pmarker is used to hold the place of the proc being processed, so
  925. * we can search for the next one downstream later.
  926. */
  927. }
  928. pcond = (tp != pp || (inpipe && tp == pp));
  929. #else /* !BACKPIPE */
  930. pcond = (tp != pp);
  931. #endif /* BACKPIPE */
  932. jobflags |= pp->p_flags;
  933. pstatus = (int) (pp->p_flags & PALLSTATES);
  934. if (pcond && linp != linbuf && !(flag & FANCY) &&
  935. ((pstatus == status && pp->p_reason == reason) ||
  936. !(flag & REASON)))
  937. xputchar(' ');
  938. else {
  939. if (pcond && linp != linbuf)
  940. xputchar('\n');
  941. if (flag & NUMBER) {
  942. #ifdef BACKPIPE
  943. pcond = ((pp == tp && !inpipe) ||
  944. (inpipe && pipetail == tp && pp == pipehead));
  945. #else /* BACKPIPE */
  946. pcond = (pp == tp);
  947. #endif /* BACKPIPE */
  948. if (pcond)
  949. xprintf("[%d]%s %c ", pp->p_index,
  950. pp->p_index < 10 ? " " : "",
  951. pp == pcurrent ? '+' :
  952. (pp == pprevious ? '-' : ' '));
  953. else
  954. xprintf(" ");
  955. }
  956. if (flag & FANCY) {
  957. xprintf("%5d ", pp->p_procid);
  958. #ifdef TCF
  959. xprintf("%11s ", sitename(pp->p_procid));
  960. #endif /* TCF */
  961. }
  962. if (flag & (REASON | AREASON)) {
  963. if (flag & NAME)
  964. format = "%-30s";
  965. else
  966. format = "%s";
  967. if (pstatus == status) {
  968. if (pp->p_reason == reason) {
  969. xprintf(format, "");
  970. goto prcomd;
  971. }
  972. else
  973. reason = (int) pp->p_reason;
  974. }
  975. else {
  976. status = pstatus;
  977. reason = (int) pp->p_reason;
  978. }
  979. switch (status) {
  980. case PRUNNING:
  981. xprintf(format, CGETS(17, 4, "Running "));
  982. break;
  983. case PINTERRUPTED:
  984. case PSTOPPED:
  985. case PSIGNALED:
  986. /*
  987. * tell what happened to the background job
  988. * From: Michael Schroeder
  989. * <mlschroe@immd4.informatik.uni-erlangen.de>
  990. */
  991. if ((flag & REASON)
  992. || ((flag & AREASON)
  993. && reason != SIGINT
  994. && (reason != SIGPIPE
  995. || (pp->p_flags & PPOU) == 0))) {
  996. char *ptr;
  997. int free_ptr;
  998. free_ptr = 0;
  999. ptr = (char *)(intptr_t)mesg[pp->p_reason & 0177].pname;
  1000. if (ptr == NULL) {
  1001. ptr = xasprintf("%s %d", CGETS(17, 5, "Signal"),
  1002. pp->p_reason & 0177);
  1003. cleanup_push(ptr, xfree);
  1004. free_ptr = 1;
  1005. }
  1006. xprintf(format, ptr);
  1007. if (free_ptr != 0)
  1008. cleanup_until(ptr);
  1009. }
  1010. else
  1011. reason = -1;
  1012. break;
  1013. case PNEXITED:
  1014. case PAEXITED:
  1015. if (flag & REASON) {
  1016. if (pp->p_reason)
  1017. xprintf(CGETS(17, 6, "Exit %-25d"), pp->p_reason);
  1018. else
  1019. xprintf(format, CGETS(17, 7, "Done"));
  1020. }
  1021. break;
  1022. default:
  1023. xprintf(CGETS(17, 8, "BUG: status=%-9o"),
  1024. status);
  1025. }
  1026. }
  1027. }
  1028. prcomd:
  1029. if (flag & NAME) {
  1030. xprintf("%S", pp->p_command);
  1031. if (pp->p_flags & PPOU)
  1032. xprintf(" |");
  1033. if (pp->p_flags & PDIAG)
  1034. xprintf("&");
  1035. }
  1036. if (flag & (REASON | AREASON) && pp->p_flags & PDUMPED)
  1037. xprintf("%s", CGETS(17, 9, " (core dumped)"));
  1038. if (tp == pp->p_friends) {
  1039. if (flag & AMPERSAND)
  1040. xprintf(" &");
  1041. if (flag & JOBDIR &&
  1042. !eq(tp->p_cwd->di_name, dcwd->di_name)) {
  1043. xprintf("%s", CGETS(17, 10, " (wd: "));
  1044. dtildepr(tp->p_cwd->di_name);
  1045. xprintf(")");
  1046. }
  1047. }
  1048. if (pp->p_flags & PPTIME && !(status & (PSTOPPED | PRUNNING))) {
  1049. if (linp != linbuf)
  1050. xprintf("\n\t");
  1051. #if defined(BSDTIMES) || defined(_SEQUENT_)
  1052. prusage(&zru, &pp->p_rusage, &pp->p_etime,
  1053. &pp->p_btime);
  1054. #else /* !BSDTIMES && !SEQUENT */
  1055. lru.tms_utime = pp->p_utime;
  1056. lru.tms_stime = pp->p_stime;
  1057. lru.tms_cutime = 0;
  1058. lru.tms_cstime = 0;
  1059. prusage(&zru, &lru, pp->p_etime,
  1060. pp->p_btime);
  1061. #endif /* !BSDTIMES && !SEQUENT */
  1062. }
  1063. #ifdef BACKPIPE
  1064. pcond = ((tp == pp->p_friends && !inpipe) ||
  1065. (inpipe && pipehead->p_friends == tp && pp == pipetail));
  1066. #else /* !BACKPIPE */
  1067. pcond = (tp == pp->p_friends);
  1068. #endif /* BACKPIPE */
  1069. if (pcond) {
  1070. if (linp != linbuf)
  1071. xputchar('\n');
  1072. if (flag & SHELLDIR && !eq(tp->p_cwd->di_name, dcwd->di_name)) {
  1073. xprintf("%s", CGETS(17, 11, "(wd now: "));
  1074. dtildepr(dcwd->di_name);
  1075. xprintf(")\n");
  1076. }
  1077. }
  1078. #ifdef BACKPIPE
  1079. if (inpipe) {
  1080. /*
  1081. * if pmaker == pipetail, we are finished that pipeline, and
  1082. * can now skip to past the head
  1083. */
  1084. if (pmarker == pipetail) {
  1085. inpipe = 0;
  1086. pp = pipehead;
  1087. }
  1088. else {
  1089. /*
  1090. * set pp to one before the one we want next, so the while below
  1091. * increments to the correct spot.
  1092. */
  1093. do
  1094. pp = pp->p_friends;
  1095. while (pp->p_friends->p_friends != pmarker);
  1096. pmarker = pp->p_friends;
  1097. }
  1098. }
  1099. pcond = ((pp = pp->p_friends) != tp || inpipe);
  1100. #else /* !BACKPIPE */
  1101. pcond = ((pp = pp->p_friends) != tp);
  1102. #endif /* BACKPIPE */
  1103. } while (pcond);
  1104. if (jobflags & PTIME && (jobflags & (PSTOPPED | PRUNNING)) == 0) {
  1105. if (jobflags & NUMBER)
  1106. xprintf(" ");
  1107. ptprint(tp);
  1108. }
  1109. return (jobflags);
  1110. }
  1111. /*
  1112. * All 4.3 BSD derived implementations are buggy and I've had enough.
  1113. * The following implementation produces similar code and works in all
  1114. * cases. The 4.3BSD one works only for <, >, !=
  1115. */
  1116. # undef timercmp
  1117. # define timercmp(tvp, uvp, cmp) \
  1118. (((tvp)->tv_sec == (uvp)->tv_sec) ? \
  1119. ((tvp)->tv_usec cmp (uvp)->tv_usec) : \
  1120. ((tvp)->tv_sec cmp (uvp)->tv_sec))
  1121. static void
  1122. ptprint(struct process *tp)
  1123. {
  1124. #ifdef BSDTIMES
  1125. struct timeval tetime, diff;
  1126. static struct timeval ztime;
  1127. struct sysrusage ru;
  1128. struct process *pp = tp;
  1129. ru = zru;
  1130. tetime = ztime;
  1131. do {
  1132. ruadd(&ru, &pp->p_rusage);
  1133. tvsub(&diff, &pp->p_etime, &pp->p_btime);
  1134. if (timercmp(&diff, &tetime, >))
  1135. tetime = diff;
  1136. } while ((pp = pp->p_friends) != tp);
  1137. prusage(&zru, &ru, &tetime, &ztime);
  1138. #else /* !BSDTIMES */
  1139. # ifdef _SEQUENT_
  1140. timeval_t tetime, diff;
  1141. static timeval_t ztime;
  1142. struct process_stats ru;
  1143. struct process *pp = tp;
  1144. ru = zru;
  1145. tetime = ztime;
  1146. do {
  1147. ruadd(&ru, &pp->p_rusage);
  1148. tvsub(&diff, &pp->p_etime, &pp->p_btime);
  1149. if (timercmp(&diff, &tetime, >))
  1150. tetime = diff;
  1151. } while ((pp = pp->p_friends) != tp);
  1152. prusage(&zru, &ru, &tetime, &ztime);
  1153. # else /* !_SEQUENT_ */
  1154. # ifndef POSIX
  1155. static time_t ztime = 0;
  1156. static time_t zu_time = 0;
  1157. static time_t zs_time = 0;
  1158. time_t tetime, diff;
  1159. time_t u_time, s_time;
  1160. # else /* POSIX */
  1161. static clock_t ztime = 0;
  1162. static clock_t zu_time = 0;
  1163. static clock_t zs_time = 0;
  1164. clock_t tetime, diff;
  1165. clock_t u_time, s_time;
  1166. # endif /* POSIX */
  1167. struct tms zts, rts;
  1168. struct process *pp = tp;
  1169. u_time = zu_time;
  1170. s_time = zs_time;
  1171. tetime = ztime;
  1172. do {
  1173. u_time += pp->p_utime;
  1174. s_time += pp->p_stime;
  1175. diff = pp->p_etime - pp->p_btime;
  1176. if (diff > tetime)
  1177. tetime = diff;
  1178. } while ((pp = pp->p_friends) != tp);
  1179. zts.tms_utime = zu_time;
  1180. zts.tms_stime = zs_time;
  1181. zts.tms_cutime = 0;
  1182. zts.tms_cstime = 0;
  1183. rts.tms_utime = u_time;
  1184. rts.tms_stime = s_time;
  1185. rts.tms_cutime = 0;
  1186. rts.tms_cstime = 0;
  1187. prusage(&zts, &rts, tetime, ztime);
  1188. # endif /* !_SEQUENT_ */
  1189. #endif /* !BSDTIMES */
  1190. }
  1191. /*
  1192. * dojobs - print all jobs
  1193. */
  1194. /*ARGSUSED*/
  1195. void
  1196. dojobs(Char **v, struct command *c)
  1197. {
  1198. struct process *pp;
  1199. int flag = NUMBER | NAME | REASON;
  1200. int i;
  1201. USE(c);
  1202. if (chkstop)
  1203. chkstop = 2;
  1204. if (*++v) {
  1205. if (v[1] || !eq(*v, STRml))
  1206. stderror(ERR_JOBS);
  1207. flag |= FANCY | JOBDIR;
  1208. }
  1209. for (i = 1; i <= pmaxindex; i++)
  1210. for (pp = proclist.p_next; pp; pp = pp->p_next)
  1211. if (pp->p_index == i && pp->p_procid == pp->p_jobid) {
  1212. pp->p_flags &= ~PNEEDNOTE;
  1213. if (!(pprint(pp, flag) & (PRUNNING | PSTOPPED)))
  1214. pflush(pp);
  1215. break;
  1216. }
  1217. }
  1218. /*
  1219. * dofg - builtin - put the job into the foreground
  1220. */
  1221. /*ARGSUSED*/
  1222. void
  1223. dofg(Char **v, struct command *c)
  1224. {
  1225. struct process *pp;
  1226. USE(c);
  1227. okpcntl();
  1228. ++v;
  1229. do {
  1230. pp = pfind(*v);
  1231. if (!pstart(pp, 1)) {
  1232. pp->p_procid = 0;
  1233. stderror(ERR_NAME|ERR_BADJOB, pp->p_command, strerror(errno));
  1234. continue;
  1235. }
  1236. pjwait(pp);
  1237. } while (*v && *++v);
  1238. }
  1239. /*
  1240. * %... - builtin - put the job into the foreground
  1241. */
  1242. /*ARGSUSED*/
  1243. void
  1244. dofg1(Char **v, struct command *c)
  1245. {
  1246. struct process *pp;
  1247. USE(c);
  1248. okpcntl();
  1249. pp = pfind(v[0]);
  1250. if (!pstart(pp, 1)) {
  1251. pp->p_procid = 0;
  1252. stderror(ERR_NAME|ERR_BADJOB, pp->p_command, strerror(errno));
  1253. return;
  1254. }
  1255. pjwait(pp);
  1256. }
  1257. /*
  1258. * dobg - builtin - put the job into the background
  1259. */
  1260. /*ARGSUSED*/
  1261. void
  1262. dobg(Char **v, struct command *c)
  1263. {
  1264. struct process *pp;
  1265. USE(c);
  1266. okpcntl();
  1267. ++v;
  1268. do {
  1269. pp = pfind(*v);
  1270. if (!pstart(pp, 0)) {
  1271. pp->p_procid = 0;
  1272. stderror(ERR_NAME|ERR_BADJOB, pp->p_command, strerror(errno));
  1273. }
  1274. } while (*v && *++v);
  1275. }
  1276. /*
  1277. * %... & - builtin - put the job into the background
  1278. */
  1279. /*ARGSUSED*/
  1280. void
  1281. dobg1(Char **v, struct command *c)
  1282. {
  1283. struct process *pp;
  1284. USE(c);
  1285. pp = pfind(v[0]);
  1286. if (!pstart(pp, 0)) {
  1287. pp->p_procid = 0;
  1288. stderror(ERR_NAME|ERR_BADJOB, pp->p_command, strerror(errno));
  1289. }
  1290. }
  1291. /*
  1292. * dostop - builtin - stop the job
  1293. */
  1294. /*ARGSUSED*/
  1295. void
  1296. dostop(Char **v, struct command *c)
  1297. {
  1298. USE(c);
  1299. #ifdef BSDJOBS
  1300. pkill(++v, SIGSTOP);
  1301. #endif /* BSDJOBS */
  1302. }
  1303. /*
  1304. * dokill - builtin - superset of kill (1)
  1305. */
  1306. /*ARGSUSED*/
  1307. void
  1308. dokill(Char **v, struct command *c)
  1309. {
  1310. int signum, len = 0;
  1311. const char *name;
  1312. Char *sigptr;
  1313. USE(c);
  1314. v++;
  1315. if (v[0] && v[0][0] == '-') {
  1316. if (v[0][1] == 'l') {
  1317. for (signum = 0; signum <= nsig; signum++) {
  1318. if ((name = mesg[signum].iname) != NULL) {
  1319. len += strlen(name) + 1;
  1320. if (len >= TermH - 1) {
  1321. xputchar('\n');
  1322. len = strlen(name) + 1;
  1323. }
  1324. xprintf("%s ", name);
  1325. }
  1326. }
  1327. xputchar('\n');
  1328. return;
  1329. }
  1330. sigptr = &v[0][1];
  1331. if (v[0][1] == 's') {
  1332. if (v[1]) {
  1333. v++;
  1334. sigptr = &v[0][0];
  1335. } else {
  1336. stderror(ERR_NAME | ERR_TOOFEW);
  1337. }
  1338. }
  1339. if (Isdigit(*sigptr)) {
  1340. char *ep;
  1341. signum = strtoul(short2str(sigptr), &ep, 0);
  1342. if (*ep || signum < 0 || signum > (MAXSIG-1))
  1343. stderror(ERR_NAME | ERR_BADSIG);
  1344. }
  1345. else {
  1346. for (signum = 0; signum <= nsig; signum++)
  1347. if (mesg[signum].iname &&
  1348. eq(sigptr, str2short(mesg[signum].iname)))
  1349. goto gotsig;
  1350. setname(short2str(sigptr));
  1351. stderror(ERR_NAME | ERR_UNKSIG);
  1352. }
  1353. gotsig:
  1354. v++;
  1355. }
  1356. else
  1357. signum = SIGTERM;
  1358. pkill(v, signum);
  1359. }
  1360. static void
  1361. pkill(Char **v, int signum)
  1362. {
  1363. struct process *pp, *np;
  1364. int jobflags = 0, err1 = 0;
  1365. pid_t pid;
  1366. Char *cp, **vp, **globbed;
  1367. /* Avoid globbing %?x patterns */
  1368. for (vp = v; vp && *vp; vp++)
  1369. if (**vp == '%')
  1370. (void) quote(*vp);
  1371. v = glob_all_or_error(v);
  1372. globbed = v;
  1373. cleanup_push(globbed, blk_cleanup);
  1374. pchild_disabled++;
  1375. cleanup_push(&pchild_disabled, disabled_cleanup);
  1376. if (setintr) {
  1377. pintr_disabled++;
  1378. cleanup_push(&pintr_disabled, disabled_cleanup);
  1379. }
  1380. while (v && (cp = *v)) {
  1381. if (*cp == '%') {
  1382. np = pp = pfind(cp);
  1383. do
  1384. jobflags |= np->p_flags;
  1385. while ((np = np->p_friends) != pp);
  1386. #ifdef BSDJOBS
  1387. switch (signum) {
  1388. case SIGSTOP:
  1389. case SIGTSTP:
  1390. case SIGTTIN:
  1391. case SIGTTOU:
  1392. if ((jobflags & PRUNNING) == 0) {
  1393. # ifdef SUSPENDED
  1394. xprintf(CGETS(17, 12, "%S: Already suspended\n"), cp);
  1395. # else /* !SUSPENDED */
  1396. xprintf(CGETS(17, 13, "%S: Already stopped\n"), cp);
  1397. # endif /* !SUSPENDED */
  1398. err1++;
  1399. goto cont;
  1400. }
  1401. break;
  1402. /*
  1403. * suspend a process, kill -CONT %, then type jobs; the shell
  1404. * says it is suspended, but it is running; thanks jaap..
  1405. */
  1406. case SIGCONT:
  1407. if (!pstart(pp, 0)) {
  1408. pp->p_procid = 0;
  1409. stderror(ERR_NAME|ERR_BADJOB, pp->p_command,
  1410. strerror(errno));
  1411. }
  1412. goto cont;
  1413. default:
  1414. break;
  1415. }
  1416. #endif /* BSDJOBS */
  1417. if (killpg(pp->p_jobid, signum) < 0) {
  1418. xprintf("%S: %s\n", cp, strerror(errno));
  1419. err1++;
  1420. }
  1421. #ifdef BSDJOBS
  1422. if (signum == SIGTERM || signum == SIGHUP)
  1423. (void) killpg(pp->p_jobid, SIGCONT);
  1424. #endif /* BSDJOBS */
  1425. }
  1426. else if (!(Isdigit(*cp) || *cp == '-'))
  1427. stderror(ERR_NAME | ERR_JOBARGS);
  1428. else {
  1429. char *ep;
  1430. #ifndef WINNT_NATIVE
  1431. pid = strtol(short2str(cp), &ep, 10);
  1432. #else
  1433. pid = strtoul(short2str(cp), &ep, 0);
  1434. #endif /* WINNT_NATIVE */
  1435. if (*ep)
  1436. stderror(ERR_NAME | ERR_JOBARGS);
  1437. else if (kill(pid, signum) < 0) {
  1438. xprintf("%d: %s\n", pid, strerror(errno));
  1439. err1++;
  1440. goto cont;
  1441. }
  1442. #ifdef BSDJOBS
  1443. if (signum == SIGTERM || signum == SIGHUP)
  1444. (void) kill(pid, SIGCONT);
  1445. #endif /* BSDJOBS */
  1446. }
  1447. cont:
  1448. v++;
  1449. }
  1450. cleanup_until(&pchild_disabled);
  1451. if (err1)
  1452. stderror(ERR_SILENT);
  1453. }
  1454. /*
  1455. * pstart - start the job in foreground/background
  1456. */
  1457. int
  1458. pstart(struct process *pp, int foregnd)
  1459. {
  1460. int rv = 0;
  1461. struct process *np;
  1462. /* We don't use jobflags in this function right now (see below) */
  1463. /* long jobflags = 0; */
  1464. pchild_disabled++;
  1465. cleanup_push(&pchild_disabled, disabled_cleanup);
  1466. np = pp;
  1467. do {
  1468. /* We don't use jobflags in this function right now (see below) */
  1469. /* jobflags |= np->p_flags; */
  1470. if (np->p_flags & (PRUNNING | PSTOPPED)) {
  1471. np->p_flags |= PRUNNING;
  1472. np->p_flags &= ~PSTOPPED;
  1473. if (foregnd)
  1474. np->p_flags |= PFOREGND;
  1475. else
  1476. np->p_flags &= ~PFOREGND;
  1477. }
  1478. } while ((np = np->p_friends) != pp);
  1479. if (!foregnd)
  1480. pclrcurr(pp);
  1481. (void) pprint(pp, foregnd ? NAME | JOBDIR : NUMBER | NAME | AMPERSAND);
  1482. /* GrP run jobcmd hook if foregrounding */
  1483. if (foregnd) {
  1484. job_cmd(pp->p_command);
  1485. }
  1486. #ifdef BSDJOBS
  1487. if (foregnd) {
  1488. rv = tcsetpgrp(FSHTTY, pp->p_jobid);
  1489. }
  1490. /*
  1491. * 1. child process of csh (shell script) receives SIGTTIN/SIGTTOU
  1492. * 2. parent process (csh) receives SIGCHLD
  1493. * 3. The "csh" signal handling function pchild() is invoked
  1494. * with a SIGCHLD signal.
  1495. * 4. pchild() calls wait3(WNOHANG) which returns 0.
  1496. * The child process is NOT ready to be waited for at this time.
  1497. * pchild() returns without picking-up the correct status
  1498. * for the child process which generated the SIGCHLD.
  1499. * 5. CONSEQUENCE : csh is UNaware that the process is stopped
  1500. * 6. THIS LINE HAS BEEN COMMENTED OUT : if (jobflags&PSTOPPED)
  1501. * (beto@aixwiz.austin.ibm.com - aug/03/91)
  1502. * 7. I removed the line completely and added extra checks for
  1503. * pstart, so that if a job gets attached to and dies inside
  1504. * a debugger it does not confuse the shell. [christos]
  1505. * 8. on the nec sx-4 there seems to be a problem, which requires
  1506. * a syscall(151, getpid(), getpid()) in osinit. Don't ask me
  1507. * what this is doing. [schott@rzg.mpg.de]
  1508. */
  1509. if (rv != -1)
  1510. rv = killpg(pp->p_jobid, SIGCONT);
  1511. #endif /* BSDJOBS */
  1512. cleanup_until(&pchild_disabled);
  1513. return rv != -1;
  1514. }
  1515. void
  1516. panystop(int neednl)
  1517. {
  1518. struct process *pp;
  1519. chkstop = 2;
  1520. for (pp = proclist.p_next; pp; pp = pp->p_next)
  1521. if (pp->p_flags & PSTOPPED)
  1522. stderror(ERR_STOPPED, neednl ? "\n" : "");
  1523. }
  1524. struct process *
  1525. pfind(Char *cp)
  1526. {
  1527. struct process *pp, *np;
  1528. if (cp == 0 || cp[1] == 0 || eq(cp, STRcent2) || eq(cp, STRcentplus)) {
  1529. if (pcurrent == NULL)
  1530. stderror(ERR_NAME | ERR_JOBCUR);
  1531. return (pcurrent);
  1532. }
  1533. if (eq(cp, STRcentminus) || eq(cp, STRcenthash)) {
  1534. if (pprevious == NULL)
  1535. stderror(ERR_NAME | ERR_JOBPREV);
  1536. return (pprevious);
  1537. }
  1538. if (Isdigit(cp[1])) {
  1539. int idx = atoi(short2str(cp + 1));
  1540. for (pp = proclist.p_next; pp; pp = pp->p_next)
  1541. if (pp->p_index == idx && pp->p_procid == pp->p_jobid)
  1542. return (pp);
  1543. stderror(ERR_NAME | ERR_NOSUCHJOB);
  1544. }
  1545. np = NULL;
  1546. for (pp = proclist.p_next; pp; pp = pp->p_next)
  1547. if (pp->p_procid == pp->p_jobid) {
  1548. if (cp[1] == '?') {
  1549. Char *dp;
  1550. for (dp = pp->p_command; *dp; dp++) {
  1551. if (*dp != cp[2])
  1552. continue;
  1553. if (prefix(cp + 2, dp))
  1554. goto match;
  1555. }
  1556. }
  1557. else if (prefix(cp + 1, pp->p_command)) {
  1558. match:
  1559. if (np)
  1560. stderror(ERR_NAME | ERR_AMBIG);
  1561. np = pp;
  1562. }
  1563. }
  1564. if (np)
  1565. return (np);
  1566. stderror(ERR_NAME | (cp[1] == '?' ? ERR_JOBPAT : ERR_NOSUCHJOB));
  1567. /* NOTREACHED */
  1568. return (0);
  1569. }
  1570. /*
  1571. * pgetcurr - find most recent job that is not pp, preferably stopped
  1572. */
  1573. static struct process *
  1574. pgetcurr(struct process *pp)
  1575. {
  1576. struct process *np;
  1577. struct process *xp = NULL;
  1578. for (np = proclist.p_next; np; np = np->p_next)
  1579. if (np != pcurrent && np != pp && np->p_procid &&
  1580. np->p_procid == np->p_jobid) {
  1581. if (np->p_flags & PSTOPPED)
  1582. return (np);
  1583. if (xp == NULL)
  1584. xp = np;
  1585. }
  1586. return (xp);
  1587. }
  1588. /*
  1589. * donotify - flag the job so as to report termination asynchronously
  1590. */
  1591. /*ARGSUSED*/
  1592. void
  1593. donotify(Char **v, struct command *c)
  1594. {
  1595. struct process *pp;
  1596. USE(c);
  1597. pp = pfind(*++v);
  1598. pp->p_flags |= PNOTIFY;
  1599. }
  1600. #ifdef SIGSYNCH
  1601. static void
  1602. synch_handler(int sno)
  1603. {
  1604. USE(sno);
  1605. }
  1606. #endif /* SIGSYNCH */
  1607. /*
  1608. * Do the fork and whatever should be done in the child side that
  1609. * should not be done if we are not forking at all (like for simple builtin's)
  1610. * Also do everything that needs any signals fiddled with in the parent side
  1611. *
  1612. * Wanttty tells whether process and/or tty pgrps are to be manipulated:
  1613. * -1: leave tty alone; inherit pgrp from parent
  1614. * 0: already have tty; manipulate process pgrps only
  1615. * 1: want to claim tty; manipulate process and tty pgrps
  1616. * It is usually just the value of tpgrp.
  1617. */
  1618. pid_t
  1619. pfork(struct command *t, int wanttty)
  1620. {
  1621. pid_t pid;
  1622. int ignint = 0;
  1623. pid_t pgrp;
  1624. #ifdef SIGSYNCH
  1625. struct sigaction osa, nsa;
  1626. #endif /* SIGSYNCH */
  1627. /*
  1628. * A child will be uninterruptible only under very special conditions.
  1629. * Remember that the semantics of '&' is implemented by disconnecting the
  1630. * process from the tty so signals do not need to ignored just for '&'.
  1631. * Thus signals are set to default action for children unless: we have had
  1632. * an "onintr -" (then specifically ignored) we are not playing with
  1633. * signals (inherit action)
  1634. */
  1635. if (setintr)
  1636. ignint = (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT))
  1637. || (gointr && eq(gointr, STRminus));
  1638. /*
  1639. * Check for maximum nesting of 16 processes to avoid Forking loops
  1640. */
  1641. if (child == 16)
  1642. stderror(ERR_NESTING, 16);
  1643. #ifdef SIGSYNCH
  1644. nsa.sa_handler = synch_handler;
  1645. sigfillset(&nsa.sa_mask);
  1646. nsa.sa_flags = SA_RESTART;
  1647. if (sigaction(SIGSYNCH, &nsa, &osa))
  1648. stderror(ERR_SYSTEM, "pfork: sigaction set", strerror(errno));
  1649. #endif /* SIGSYNCH */
  1650. /*
  1651. * Hold pchild() until we have the process installed in our table.
  1652. */
  1653. if (wanttty < 0) {
  1654. pchild_disabled++;
  1655. cleanup_push(&pchild_disabled, disabled_cleanup);
  1656. }
  1657. while ((pid = fork()) == -1)
  1658. if (setintr == 0)
  1659. (void) sleep(FORKSLEEP);
  1660. else
  1661. stderror(ERR_NOPROC);
  1662. if (pid == 0) {
  1663. (void)cleanup_push_mark(); /* Never to be popped */
  1664. pchild_disabled = 0;
  1665. settimes();
  1666. pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
  1667. pflushall();
  1668. pcurrjob = NULL;
  1669. #if !defined(BSDTIMES) && !defined(_SEQUENT_)
  1670. timesdone = 0;
  1671. #endif /* !defined(BSDTIMES) && !defined(_SEQUENT_) */
  1672. child++;
  1673. if (setintr) {
  1674. setintr = 0; /* until I think otherwise */
  1675. /*
  1676. * Children just get blown away on SIGINT, SIGQUIT unless "onintr
  1677. * -" seen.
  1678. */
  1679. (void) signal(SIGINT, ignint ? SIG_IGN : SIG_DFL);
  1680. (void) signal(SIGQUIT, ignint ? SIG_IGN : SIG_DFL);
  1681. #ifdef BSDJOBS
  1682. if (wanttty >= 0) {
  1683. /* make stoppable */
  1684. (void) signal(SIGTSTP, SIG_DFL);
  1685. (void) signal(SIGTTIN, SIG_DFL);
  1686. (void) signal(SIGTTOU, SIG_DFL);
  1687. }
  1688. #endif /* BSDJOBS */
  1689. sigaction(SIGTERM, &parterm, NULL);
  1690. }
  1691. else if (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT)) {
  1692. (void) signal(SIGINT, SIG_IGN);
  1693. (void) signal(SIGQUIT, SIG_IGN);
  1694. }
  1695. #ifdef OREO
  1696. signal(SIGIO, SIG_IGN); /* ignore SIGIO in child too */
  1697. #endif /* OREO */
  1698. pgetty(wanttty, pgrp);
  1699. /*
  1700. * Nohup and nice apply only to NODE_COMMAND's but it would be nice
  1701. * (?!?) if you could say "nohup (foo;bar)" Then the parser would have
  1702. * to know about nice/nohup/time
  1703. */
  1704. if (t->t_dflg & F_NOHUP)
  1705. (void) signal(SIGHUP, SIG_IGN);
  1706. if (t->t_dflg & F_NICE) {
  1707. int nval = SIGN_EXTEND_CHAR(t->t_nice);
  1708. #ifdef HAVE_SETPRIORITY
  1709. if (setpriority(PRIO_PROCESS, 0, nval) == -1 && errno)
  1710. stderror(ERR_SYSTEM, "setpriority", strerror(errno));
  1711. #else /* !HAVE_SETPRIORITY */
  1712. (void) nice(nval);
  1713. #endif /* !HAVE_SETPRIORITY */
  1714. }
  1715. #ifdef F_VER
  1716. if (t->t_dflg & F_VER) {
  1717. tsetenv(STRSYSTYPE, t->t_systype ? STRbsd43 : STRsys53);
  1718. dohash(NULL, NULL);
  1719. }
  1720. #endif /* F_VER */
  1721. #ifdef SIGSYNCH
  1722. /* rfw 8/89 now parent can continue */
  1723. if (kill(getppid(), SIGSYNCH))
  1724. stderror(ERR_SYSTEM, "pfork child: kill", strerror(errno));
  1725. #endif /* SIGSYNCH */
  1726. }
  1727. else {
  1728. #ifdef POSIXJOBS
  1729. if (wanttty >= 0) {
  1730. /*
  1731. * `Walking' process group fix from Beto Appleton.
  1732. * (beto@aixwiz.austin.ibm.com)
  1733. * If setpgid fails at this point that means that
  1734. * our process leader has died. We flush the current
  1735. * job and become the process leader ourselves.
  1736. * The parent will figure that out later.
  1737. */
  1738. pgrp = pcurrjob ? pcurrjob->p_jobid : pid;
  1739. if (setpgid(pid, pgrp) == -1 && errno == EPERM) {
  1740. pcurrjob = NULL;
  1741. /*
  1742. * We don't care if this causes an error here;
  1743. * then we are already in the right process group
  1744. */
  1745. (void) setpgid(pid, pgrp = pid);
  1746. }
  1747. }
  1748. #endif /* POSIXJOBS */
  1749. palloc(pid, t);
  1750. #ifdef SIGSYNCH
  1751. {
  1752. sigset_t pause_mask;
  1753. /*
  1754. * rfw 8/89 Wait for child to own terminal. Solves half of ugly
  1755. * synchronization problem. With this change, we know that the only
  1756. * reason setpgrp to a previous process in a pipeline can fail is that
  1757. * the previous process has already exited. Without this hack, he may
  1758. * either have exited or not yet started to run. Two uglies become
  1759. * one.
  1760. */
  1761. sigprocmask(SIG_BLOCK, NULL, &pause);
  1762. sigdelset(&pause_mask, SIGCHLD);
  1763. sigdelset(&pause_mask, SIGSYNCH);
  1764. sigsuspend(&pause_mask);
  1765. (void)handle_pending_signals();
  1766. if (sigaction(SIGSYNCH, &osa, NULL))
  1767. stderror(ERR_SYSTEM, "pfork parent: sigaction restore",
  1768. strerror(errno));
  1769. }
  1770. #endif /* SIGSYNCH */
  1771. if (wanttty < 0)
  1772. cleanup_until(&pchild_disabled);
  1773. }
  1774. return (pid);
  1775. }
  1776. static void
  1777. okpcntl(void)
  1778. {
  1779. if (tpgrp == -1)
  1780. stderror(ERR_JOBCONTROL);
  1781. if (tpgrp == 0)
  1782. stderror(ERR_JOBCTRLSUB);
  1783. }
  1784. static void
  1785. setttypgrp(int pgrp)
  1786. {
  1787. /*
  1788. * If we are piping out a builtin, eg. 'echo | more' things can go
  1789. * out of sequence, i.e. the more can run before the echo. This
  1790. * can happen even if we have vfork, since the echo will be forked
  1791. * with the regular fork. In this case, we need to set the tty
  1792. * pgrp ourselves. If that happens, then the process will be still
  1793. * alive. And the tty process group will already be set.
  1794. * This should fix the famous sequent problem as a side effect:
  1795. * The controlling terminal is lost if all processes in the
  1796. * terminal process group are zombies. In this case tcgetpgrp()
  1797. * returns 0. If this happens we must set the terminal process
  1798. * group again.
  1799. */
  1800. if (tcgetpgrp(FSHTTY) != pgrp) {
  1801. #ifdef POSIXJOBS
  1802. struct sigaction old;
  1803. /*
  1804. * tcsetpgrp will set SIGTTOU to all the the processes in
  1805. * the background according to POSIX... We ignore this here.
  1806. */
  1807. sigaction(SIGTTOU, NULL, &old);
  1808. signal(SIGTTOU, SIG_IGN);
  1809. #endif
  1810. (void) tcsetpgrp(FSHTTY, pgrp);
  1811. # ifdef POSIXJOBS
  1812. sigaction(SIGTTOU, &old, NULL);
  1813. # endif
  1814. }
  1815. }
  1816. /*
  1817. * if we don't have vfork(), things can still go in the wrong order
  1818. * resulting in the famous 'Stopped (tty output)'. But some systems
  1819. * don't permit the setpgid() call, (these are more recent secure
  1820. * systems such as ibm's aix), when they do. Then we'd rather print
  1821. * an error message than hang the shell!
  1822. * I am open to suggestions how to fix that.
  1823. */
  1824. void
  1825. pgetty(int wanttty, pid_t pgrp)
  1826. {
  1827. #ifdef BSDJOBS
  1828. # ifdef POSIXJOBS
  1829. sigset_t oset, set;
  1830. # endif /* POSIXJOBS */
  1831. jobdebug_xprintf(("wanttty %d pid %d opgrp%d pgrp %d tpgrp %d\n",
  1832. wanttty, (int)getpid(), (int)pgrp, (int)mygetpgrp(),
  1833. (int)tcgetpgrp(FSHTTY)));
  1834. # ifdef POSIXJOBS
  1835. /*
  1836. * christos: I am blocking the tty signals till I've set things
  1837. * correctly....
  1838. */
  1839. if (wanttty > 0) {
  1840. sigemptyset(&set);
  1841. sigaddset(&set, SIGTSTP);
  1842. sigaddset(&set, SIGTTIN);
  1843. (void)sigprocmask(SIG_BLOCK, &set, &oset);
  1844. cleanup_push(&oset, sigprocmask_cleanup);
  1845. }
  1846. # endif /* POSIXJOBS */
  1847. # ifndef POSIXJOBS
  1848. if (wanttty > 0)
  1849. setttypgrp(pgrp);
  1850. # endif /* !POSIXJOBS */
  1851. /*
  1852. * From: Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de>
  1853. * Don't check for tpgrp >= 0 so even non-interactive shells give
  1854. * background jobs process groups Same for the comparison in the other part
  1855. * of the #ifdef
  1856. */
  1857. if (wanttty >= 0) {
  1858. if (setpgid(0, pgrp) == -1) {
  1859. # ifdef POSIXJOBS
  1860. /* Walking process group fix; see above */
  1861. if (setpgid(0, pgrp = getpid()) == -1) {
  1862. # endif /* POSIXJOBS */
  1863. stderror(ERR_SYSTEM, "setpgid child:\n", strerror(errno));
  1864. xexit(0);
  1865. # ifdef POSIXJOBS
  1866. }
  1867. wanttty = pgrp; /* Now we really want the tty, since we became the
  1868. * the process group leader
  1869. */
  1870. # endif /* POSIXJOBS */
  1871. }
  1872. }
  1873. # ifdef POSIXJOBS
  1874. if (wanttty > 0) {
  1875. setttypgrp(pgrp);
  1876. cleanup_until(&oset);
  1877. }
  1878. # endif /* POSIXJOBS */
  1879. jobdebug_xprintf(("wanttty %d pid %d pgrp %d tpgrp %d\n",
  1880. wanttty, getpid(), mygetpgrp(), tcgetpgrp(FSHTTY)));
  1881. if (tpgrp > 0)
  1882. tpgrp = 0; /* gave tty away */
  1883. #endif /* BSDJOBS */
  1884. }