PageRenderTime 55ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/src/freebsd/bin/sh/jobs.c

https://bitbucket.org/killerpenguinassassins/open_distrib_devel
C | 1407 lines | 1180 code | 107 blank | 120 comment | 479 complexity | 217d20dcdd0d19bb7451ef3931701fd5 MD5 | raw file
Possible License(s): CC0-1.0, MIT, LGPL-2.0, LGPL-3.0, WTFPL, GPL-2.0, BSD-2-Clause, AGPL-3.0, CC-BY-SA-3.0, MPL-2.0, JSON, BSD-3-Clause-No-Nuclear-License-2014, LGPL-2.1, CPL-1.0, AGPL-1.0, 0BSD, ISC, Apache-2.0, GPL-3.0, IPL-1.0, MPL-2.0-no-copyleft-exception, BSD-3-Clause
  1. /*-
  2. * Copyright (c) 1991, 1993
  3. * The Regents of the University of California. All rights reserved.
  4. *
  5. * This code is derived from software contributed to Berkeley by
  6. * Kenneth Almquist.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in the
  15. * documentation and/or other materials provided with the distribution.
  16. * 4. Neither the name of the University nor the names of its contributors
  17. * may be used to endorse or promote products derived from this software
  18. * without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  21. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  23. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  24. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  25. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  26. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  27. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  28. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  29. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30. * SUCH DAMAGE.
  31. */
  32. #ifndef lint
  33. #if 0
  34. static char sccsid[] = "@(#)jobs.c 8.5 (Berkeley) 5/4/95";
  35. #endif
  36. #endif /* not lint */
  37. #include <sys/cdefs.h>
  38. __FBSDID("$FreeBSD$");
  39. #include <sys/ioctl.h>
  40. #include <sys/param.h>
  41. #include <sys/resource.h>
  42. #include <sys/time.h>
  43. #include <sys/wait.h>
  44. #include <errno.h>
  45. #include <fcntl.h>
  46. #include <paths.h>
  47. #include <signal.h>
  48. #include <stddef.h>
  49. #include <stdlib.h>
  50. #include <unistd.h>
  51. #include "shell.h"
  52. #if JOBS
  53. #include <termios.h>
  54. #undef CEOF /* syntax.h redefines this */
  55. #endif
  56. #include "redir.h"
  57. #include "exec.h"
  58. #include "show.h"
  59. #include "main.h"
  60. #include "parser.h"
  61. #include "nodes.h"
  62. #include "jobs.h"
  63. #include "options.h"
  64. #include "trap.h"
  65. #include "syntax.h"
  66. #include "input.h"
  67. #include "output.h"
  68. #include "memalloc.h"
  69. #include "error.h"
  70. #include "mystring.h"
  71. #include "var.h"
  72. #include "builtins.h"
  73. static struct job *jobtab; /* array of jobs */
  74. static int njobs; /* size of array */
  75. MKINIT pid_t backgndpid = -1; /* pid of last background process */
  76. MKINIT struct job *bgjob = NULL; /* last background process */
  77. #if JOBS
  78. static struct job *jobmru; /* most recently used job list */
  79. static pid_t initialpgrp; /* pgrp of shell on invocation */
  80. #endif
  81. int in_waitcmd = 0; /* are we in waitcmd()? */
  82. int in_dowait = 0; /* are we in dowait()? */
  83. volatile sig_atomic_t breakwaitcmd = 0; /* should wait be terminated? */
  84. static int ttyfd = -1;
  85. #if JOBS
  86. static void restartjob(struct job *);
  87. #endif
  88. static void freejob(struct job *);
  89. static struct job *getjob(char *);
  90. pid_t getjobpgrp(char *);
  91. static pid_t dowait(int, struct job *);
  92. static pid_t waitproc(int, int *);
  93. static void checkzombies(void);
  94. static void cmdtxt(union node *);
  95. static void cmdputs(const char *);
  96. #if JOBS
  97. static void setcurjob(struct job *);
  98. static void deljob(struct job *);
  99. static struct job *getcurjob(struct job *);
  100. #endif
  101. static void printjobcmd(struct job *);
  102. static void showjob(struct job *, int);
  103. /*
  104. * Turn job control on and off.
  105. */
  106. MKINIT int jobctl;
  107. #if JOBS
  108. void
  109. setjobctl(int on)
  110. {
  111. int i;
  112. if (on == jobctl || rootshell == 0)
  113. return;
  114. if (on) {
  115. if (ttyfd != -1)
  116. close(ttyfd);
  117. if ((ttyfd = open(_PATH_TTY, O_RDWR)) < 0) {
  118. i = 0;
  119. while (i <= 2 && !isatty(i))
  120. i++;
  121. if (i > 2 || (ttyfd = fcntl(i, F_DUPFD, 10)) < 0)
  122. goto out;
  123. }
  124. if (ttyfd < 10) {
  125. /*
  126. * Keep our TTY file descriptor out of the way of
  127. * the user's redirections.
  128. */
  129. if ((i = fcntl(ttyfd, F_DUPFD, 10)) < 0) {
  130. close(ttyfd);
  131. ttyfd = -1;
  132. goto out;
  133. }
  134. close(ttyfd);
  135. ttyfd = i;
  136. }
  137. if (fcntl(ttyfd, F_SETFD, FD_CLOEXEC) < 0) {
  138. close(ttyfd);
  139. ttyfd = -1;
  140. goto out;
  141. }
  142. do { /* while we are in the background */
  143. initialpgrp = tcgetpgrp(ttyfd);
  144. if (initialpgrp < 0) {
  145. out: out2fmt_flush("sh: can't access tty; job control turned off\n");
  146. mflag = 0;
  147. return;
  148. }
  149. if (initialpgrp != getpgrp()) {
  150. kill(0, SIGTTIN);
  151. continue;
  152. }
  153. } while (0);
  154. setsignal(SIGTSTP);
  155. setsignal(SIGTTOU);
  156. setsignal(SIGTTIN);
  157. setpgid(0, rootpid);
  158. tcsetpgrp(ttyfd, rootpid);
  159. } else { /* turning job control off */
  160. setpgid(0, initialpgrp);
  161. tcsetpgrp(ttyfd, initialpgrp);
  162. close(ttyfd);
  163. ttyfd = -1;
  164. setsignal(SIGTSTP);
  165. setsignal(SIGTTOU);
  166. setsignal(SIGTTIN);
  167. }
  168. jobctl = on;
  169. }
  170. #endif
  171. #if JOBS
  172. int
  173. fgcmd(int argc __unused, char **argv)
  174. {
  175. struct job *jp;
  176. pid_t pgrp;
  177. int status;
  178. jp = getjob(argv[1]);
  179. if (jp->jobctl == 0)
  180. error("job not created under job control");
  181. printjobcmd(jp);
  182. flushout(&output);
  183. pgrp = jp->ps[0].pid;
  184. tcsetpgrp(ttyfd, pgrp);
  185. restartjob(jp);
  186. jp->foreground = 1;
  187. INTOFF;
  188. status = waitforjob(jp, (int *)NULL);
  189. INTON;
  190. return status;
  191. }
  192. int
  193. bgcmd(int argc, char **argv)
  194. {
  195. struct job *jp;
  196. do {
  197. jp = getjob(*++argv);
  198. if (jp->jobctl == 0)
  199. error("job not created under job control");
  200. if (jp->state == JOBDONE)
  201. continue;
  202. restartjob(jp);
  203. jp->foreground = 0;
  204. out1fmt("[%td] ", jp - jobtab + 1);
  205. printjobcmd(jp);
  206. } while (--argc > 1);
  207. return 0;
  208. }
  209. static void
  210. restartjob(struct job *jp)
  211. {
  212. struct procstat *ps;
  213. int i;
  214. if (jp->state == JOBDONE)
  215. return;
  216. setcurjob(jp);
  217. INTOFF;
  218. kill(-jp->ps[0].pid, SIGCONT);
  219. for (ps = jp->ps, i = jp->nprocs ; --i >= 0 ; ps++) {
  220. if (WIFSTOPPED(ps->status)) {
  221. ps->status = -1;
  222. jp->state = 0;
  223. }
  224. }
  225. INTON;
  226. }
  227. #endif
  228. int
  229. jobscmd(int argc, char *argv[])
  230. {
  231. char *id;
  232. int ch, mode;
  233. optind = optreset = 1;
  234. opterr = 0;
  235. mode = SHOWJOBS_DEFAULT;
  236. while ((ch = getopt(argc, argv, "lps")) != -1) {
  237. switch (ch) {
  238. case 'l':
  239. mode = SHOWJOBS_VERBOSE;
  240. break;
  241. case 'p':
  242. mode = SHOWJOBS_PGIDS;
  243. break;
  244. case 's':
  245. mode = SHOWJOBS_PIDS;
  246. break;
  247. case '?':
  248. default:
  249. error("unknown option: -%c", optopt);
  250. }
  251. }
  252. argc -= optind;
  253. argv += optind;
  254. if (argc == 0)
  255. showjobs(0, mode);
  256. else
  257. while ((id = *argv++) != NULL)
  258. showjob(getjob(id), mode);
  259. return (0);
  260. }
  261. static void
  262. printjobcmd(struct job *jp)
  263. {
  264. struct procstat *ps;
  265. int i;
  266. for (ps = jp->ps, i = jp->nprocs ; --i >= 0 ; ps++) {
  267. out1str(ps->cmd);
  268. if (i > 0)
  269. out1str(" | ");
  270. }
  271. out1c('\n');
  272. }
  273. static void
  274. showjob(struct job *jp, int mode)
  275. {
  276. char s[64];
  277. char statestr[64];
  278. struct procstat *ps;
  279. struct job *j;
  280. int col, curr, i, jobno, prev, procno;
  281. char c;
  282. procno = (mode == SHOWJOBS_PGIDS) ? 1 : jp->nprocs;
  283. jobno = jp - jobtab + 1;
  284. curr = prev = 0;
  285. #if JOBS
  286. if ((j = getcurjob(NULL)) != NULL) {
  287. curr = j - jobtab + 1;
  288. if ((j = getcurjob(j)) != NULL)
  289. prev = j - jobtab + 1;
  290. }
  291. #endif
  292. ps = jp->ps + jp->nprocs - 1;
  293. if (jp->state == 0) {
  294. strcpy(statestr, "Running");
  295. #if JOBS
  296. } else if (jp->state == JOBSTOPPED) {
  297. while (!WIFSTOPPED(ps->status) && ps > jp->ps)
  298. ps--;
  299. if (WIFSTOPPED(ps->status))
  300. i = WSTOPSIG(ps->status);
  301. else
  302. i = -1;
  303. if (i > 0 && i < sys_nsig && sys_siglist[i])
  304. strcpy(statestr, sys_siglist[i]);
  305. else
  306. strcpy(statestr, "Suspended");
  307. #endif
  308. } else if (WIFEXITED(ps->status)) {
  309. if (WEXITSTATUS(ps->status) == 0)
  310. strcpy(statestr, "Done");
  311. else
  312. fmtstr(statestr, 64, "Done(%d)",
  313. WEXITSTATUS(ps->status));
  314. } else {
  315. i = WTERMSIG(ps->status);
  316. if (i > 0 && i < sys_nsig && sys_siglist[i])
  317. strcpy(statestr, sys_siglist[i]);
  318. else
  319. fmtstr(statestr, 64, "Signal %d", i);
  320. if (WCOREDUMP(ps->status))
  321. strcat(statestr, " (core dumped)");
  322. }
  323. for (ps = jp->ps ; ; ps++) { /* for each process */
  324. if (mode == SHOWJOBS_PIDS || mode == SHOWJOBS_PGIDS) {
  325. out1fmt("%d\n", (int)ps->pid);
  326. goto skip;
  327. }
  328. if (mode != SHOWJOBS_VERBOSE && ps != jp->ps)
  329. goto skip;
  330. if (jobno == curr && ps == jp->ps)
  331. c = '+';
  332. else if (jobno == prev && ps == jp->ps)
  333. c = '-';
  334. else
  335. c = ' ';
  336. if (ps == jp->ps)
  337. fmtstr(s, 64, "[%d] %c ", jobno, c);
  338. else
  339. fmtstr(s, 64, " %c ", c);
  340. out1str(s);
  341. col = strlen(s);
  342. if (mode == SHOWJOBS_VERBOSE) {
  343. fmtstr(s, 64, "%d ", (int)ps->pid);
  344. out1str(s);
  345. col += strlen(s);
  346. }
  347. if (ps == jp->ps) {
  348. out1str(statestr);
  349. col += strlen(statestr);
  350. }
  351. do {
  352. out1c(' ');
  353. col++;
  354. } while (col < 30);
  355. if (mode == SHOWJOBS_VERBOSE) {
  356. out1str(ps->cmd);
  357. out1c('\n');
  358. } else
  359. printjobcmd(jp);
  360. skip: if (--procno <= 0)
  361. break;
  362. }
  363. }
  364. /*
  365. * Print a list of jobs. If "change" is nonzero, only print jobs whose
  366. * statuses have changed since the last call to showjobs.
  367. *
  368. * If the shell is interrupted in the process of creating a job, the
  369. * result may be a job structure containing zero processes. Such structures
  370. * will be freed here.
  371. */
  372. void
  373. showjobs(int change, int mode)
  374. {
  375. int jobno;
  376. struct job *jp;
  377. TRACE(("showjobs(%d) called\n", change));
  378. checkzombies();
  379. for (jobno = 1, jp = jobtab ; jobno <= njobs ; jobno++, jp++) {
  380. if (! jp->used)
  381. continue;
  382. if (jp->nprocs == 0) {
  383. freejob(jp);
  384. continue;
  385. }
  386. if (change && ! jp->changed)
  387. continue;
  388. showjob(jp, mode);
  389. jp->changed = 0;
  390. /* Hack: discard jobs for which $! has not been referenced
  391. * in interactive mode when they terminate.
  392. */
  393. if (jp->state == JOBDONE && !jp->remembered &&
  394. (iflag || jp != bgjob)) {
  395. freejob(jp);
  396. }
  397. }
  398. }
  399. /*
  400. * Mark a job structure as unused.
  401. */
  402. static void
  403. freejob(struct job *jp)
  404. {
  405. struct procstat *ps;
  406. int i;
  407. INTOFF;
  408. if (bgjob == jp)
  409. bgjob = NULL;
  410. for (i = jp->nprocs, ps = jp->ps ; --i >= 0 ; ps++) {
  411. if (ps->cmd != nullstr)
  412. ckfree(ps->cmd);
  413. }
  414. if (jp->ps != &jp->ps0)
  415. ckfree(jp->ps);
  416. jp->used = 0;
  417. #if JOBS
  418. deljob(jp);
  419. #endif
  420. INTON;
  421. }
  422. int
  423. waitcmd(int argc, char **argv)
  424. {
  425. struct job *job;
  426. int status, retval;
  427. struct job *jp;
  428. if (argc > 1) {
  429. job = getjob(argv[1]);
  430. } else {
  431. job = NULL;
  432. }
  433. /*
  434. * Loop until a process is terminated or stopped, or a SIGINT is
  435. * received.
  436. */
  437. in_waitcmd++;
  438. do {
  439. if (job != NULL) {
  440. if (job->state) {
  441. status = job->ps[job->nprocs - 1].status;
  442. if (WIFEXITED(status))
  443. retval = WEXITSTATUS(status);
  444. #if JOBS
  445. else if (WIFSTOPPED(status))
  446. retval = WSTOPSIG(status) + 128;
  447. #endif
  448. else
  449. retval = WTERMSIG(status) + 128;
  450. if (! iflag || ! job->changed)
  451. freejob(job);
  452. else {
  453. job->remembered = 0;
  454. if (job == bgjob)
  455. bgjob = NULL;
  456. }
  457. in_waitcmd--;
  458. return retval;
  459. }
  460. } else {
  461. for (jp = jobtab ; jp < jobtab + njobs; jp++)
  462. if (jp->used && jp->state == JOBDONE) {
  463. if (! iflag || ! jp->changed)
  464. freejob(jp);
  465. else {
  466. jp->remembered = 0;
  467. if (jp == bgjob)
  468. bgjob = NULL;
  469. }
  470. }
  471. for (jp = jobtab ; ; jp++) {
  472. if (jp >= jobtab + njobs) { /* no running procs */
  473. in_waitcmd--;
  474. return 0;
  475. }
  476. if (jp->used && jp->state == 0)
  477. break;
  478. }
  479. }
  480. } while (dowait(1, (struct job *)NULL) != -1);
  481. in_waitcmd--;
  482. return 0;
  483. }
  484. int
  485. jobidcmd(int argc __unused, char **argv)
  486. {
  487. struct job *jp;
  488. int i;
  489. jp = getjob(argv[1]);
  490. for (i = 0 ; i < jp->nprocs ; ) {
  491. out1fmt("%d", (int)jp->ps[i].pid);
  492. out1c(++i < jp->nprocs? ' ' : '\n');
  493. }
  494. return 0;
  495. }
  496. /*
  497. * Convert a job name to a job structure.
  498. */
  499. static struct job *
  500. getjob(char *name)
  501. {
  502. int jobno;
  503. struct job *found, *jp;
  504. pid_t pid;
  505. int i;
  506. if (name == NULL) {
  507. #if JOBS
  508. currentjob: if ((jp = getcurjob(NULL)) == NULL)
  509. error("No current job");
  510. return (jp);
  511. #else
  512. error("No current job");
  513. #endif
  514. } else if (name[0] == '%') {
  515. if (is_digit(name[1])) {
  516. jobno = number(name + 1);
  517. if (jobno > 0 && jobno <= njobs
  518. && jobtab[jobno - 1].used != 0)
  519. return &jobtab[jobno - 1];
  520. #if JOBS
  521. } else if (name[1] == '%' && name[2] == '\0') {
  522. goto currentjob;
  523. } else if (name[1] == '+' && name[2] == '\0') {
  524. goto currentjob;
  525. } else if (name[1] == '-' && name[2] == '\0') {
  526. if ((jp = getcurjob(NULL)) == NULL ||
  527. (jp = getcurjob(jp)) == NULL)
  528. error("No previous job");
  529. return (jp);
  530. #endif
  531. } else if (name[1] == '?') {
  532. found = NULL;
  533. for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
  534. if (jp->used && jp->nprocs > 0
  535. && strstr(jp->ps[0].cmd, name + 2) != NULL) {
  536. if (found)
  537. error("%s: ambiguous", name);
  538. found = jp;
  539. }
  540. }
  541. if (found != NULL)
  542. return (found);
  543. } else {
  544. found = NULL;
  545. for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
  546. if (jp->used && jp->nprocs > 0
  547. && prefix(name + 1, jp->ps[0].cmd)) {
  548. if (found)
  549. error("%s: ambiguous", name);
  550. found = jp;
  551. }
  552. }
  553. if (found)
  554. return found;
  555. }
  556. } else if (is_number(name)) {
  557. pid = (pid_t)number(name);
  558. for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
  559. if (jp->used && jp->nprocs > 0
  560. && jp->ps[jp->nprocs - 1].pid == pid)
  561. return jp;
  562. }
  563. }
  564. error("No such job: %s", name);
  565. /*NOTREACHED*/
  566. return NULL;
  567. }
  568. pid_t
  569. getjobpgrp(char *name)
  570. {
  571. struct job *jp;
  572. jp = getjob(name);
  573. return -jp->ps[0].pid;
  574. }
  575. /*
  576. * Return a new job structure,
  577. */
  578. struct job *
  579. makejob(union node *node __unused, int nprocs)
  580. {
  581. int i;
  582. struct job *jp;
  583. for (i = njobs, jp = jobtab ; ; jp++) {
  584. if (--i < 0) {
  585. INTOFF;
  586. if (njobs == 0) {
  587. jobtab = ckmalloc(4 * sizeof jobtab[0]);
  588. #if JOBS
  589. jobmru = NULL;
  590. #endif
  591. } else {
  592. jp = ckmalloc((njobs + 4) * sizeof jobtab[0]);
  593. memcpy(jp, jobtab, njobs * sizeof jp[0]);
  594. #if JOBS
  595. /* Relocate `next' pointers and list head */
  596. if (jobmru != NULL)
  597. jobmru = &jp[jobmru - jobtab];
  598. for (i = 0; i < njobs; i++)
  599. if (jp[i].next != NULL)
  600. jp[i].next = &jp[jp[i].next -
  601. jobtab];
  602. #endif
  603. if (bgjob != NULL)
  604. bgjob = &jp[bgjob - jobtab];
  605. /* Relocate `ps' pointers */
  606. for (i = 0; i < njobs; i++)
  607. if (jp[i].ps == &jobtab[i].ps0)
  608. jp[i].ps = &jp[i].ps0;
  609. ckfree(jobtab);
  610. jobtab = jp;
  611. }
  612. jp = jobtab + njobs;
  613. for (i = 4 ; --i >= 0 ; jobtab[njobs++].used = 0);
  614. INTON;
  615. break;
  616. }
  617. if (jp->used == 0)
  618. break;
  619. }
  620. INTOFF;
  621. jp->state = 0;
  622. jp->used = 1;
  623. jp->changed = 0;
  624. jp->nprocs = 0;
  625. jp->foreground = 0;
  626. jp->remembered = 0;
  627. #if JOBS
  628. jp->jobctl = jobctl;
  629. jp->next = NULL;
  630. #endif
  631. if (nprocs > 1) {
  632. jp->ps = ckmalloc(nprocs * sizeof (struct procstat));
  633. } else {
  634. jp->ps = &jp->ps0;
  635. }
  636. INTON;
  637. TRACE(("makejob(%p, %d) returns %%%td\n", (void *)node, nprocs,
  638. jp - jobtab + 1));
  639. return jp;
  640. }
  641. #if JOBS
  642. static void
  643. setcurjob(struct job *cj)
  644. {
  645. struct job *jp, *prev;
  646. for (prev = NULL, jp = jobmru; jp != NULL; prev = jp, jp = jp->next) {
  647. if (jp == cj) {
  648. if (prev != NULL)
  649. prev->next = jp->next;
  650. else
  651. jobmru = jp->next;
  652. jp->next = jobmru;
  653. jobmru = cj;
  654. return;
  655. }
  656. }
  657. cj->next = jobmru;
  658. jobmru = cj;
  659. }
  660. static void
  661. deljob(struct job *j)
  662. {
  663. struct job *jp, *prev;
  664. for (prev = NULL, jp = jobmru; jp != NULL; prev = jp, jp = jp->next) {
  665. if (jp == j) {
  666. if (prev != NULL)
  667. prev->next = jp->next;
  668. else
  669. jobmru = jp->next;
  670. return;
  671. }
  672. }
  673. }
  674. /*
  675. * Return the most recently used job that isn't `nj', and preferably one
  676. * that is stopped.
  677. */
  678. static struct job *
  679. getcurjob(struct job *nj)
  680. {
  681. struct job *jp;
  682. /* Try to find a stopped one.. */
  683. for (jp = jobmru; jp != NULL; jp = jp->next)
  684. if (jp->used && jp != nj && jp->state == JOBSTOPPED)
  685. return (jp);
  686. /* Otherwise the most recently used job that isn't `nj' */
  687. for (jp = jobmru; jp != NULL; jp = jp->next)
  688. if (jp->used && jp != nj)
  689. return (jp);
  690. return (NULL);
  691. }
  692. #endif
  693. /*
  694. * Fork of a subshell. If we are doing job control, give the subshell its
  695. * own process group. Jp is a job structure that the job is to be added to.
  696. * N is the command that will be evaluated by the child. Both jp and n may
  697. * be NULL. The mode parameter can be one of the following:
  698. * FORK_FG - Fork off a foreground process.
  699. * FORK_BG - Fork off a background process.
  700. * FORK_NOJOB - Like FORK_FG, but don't give the process its own
  701. * process group even if job control is on.
  702. *
  703. * When job control is turned off, background processes have their standard
  704. * input redirected to /dev/null (except for the second and later processes
  705. * in a pipeline).
  706. */
  707. pid_t
  708. forkshell(struct job *jp, union node *n, int mode)
  709. {
  710. pid_t pid;
  711. pid_t pgrp;
  712. TRACE(("forkshell(%%%td, %p, %d) called\n", jp - jobtab, (void *)n,
  713. mode));
  714. INTOFF;
  715. if (mode == FORK_BG && (jp == NULL || jp->nprocs == 0))
  716. checkzombies();
  717. flushall();
  718. pid = fork();
  719. if (pid == -1) {
  720. TRACE(("Fork failed, errno=%d\n", errno));
  721. INTON;
  722. error("Cannot fork: %s", strerror(errno));
  723. }
  724. if (pid == 0) {
  725. struct job *p;
  726. int wasroot;
  727. int i;
  728. TRACE(("Child shell %d\n", (int)getpid()));
  729. wasroot = rootshell;
  730. rootshell = 0;
  731. handler = &main_handler;
  732. closescript();
  733. INTON;
  734. forcelocal = 0;
  735. clear_traps();
  736. #if JOBS
  737. jobctl = 0; /* do job control only in root shell */
  738. if (wasroot && mode != FORK_NOJOB && mflag) {
  739. if (jp == NULL || jp->nprocs == 0)
  740. pgrp = getpid();
  741. else
  742. pgrp = jp->ps[0].pid;
  743. if (setpgid(0, pgrp) == 0 && mode == FORK_FG) {
  744. /*** this causes superfluous TIOCSPGRPS ***/
  745. if (tcsetpgrp(ttyfd, pgrp) < 0)
  746. error("tcsetpgrp failed, errno=%d", errno);
  747. }
  748. setsignal(SIGTSTP);
  749. setsignal(SIGTTOU);
  750. } else if (mode == FORK_BG) {
  751. ignoresig(SIGINT);
  752. ignoresig(SIGQUIT);
  753. if ((jp == NULL || jp->nprocs == 0) &&
  754. ! fd0_redirected_p ()) {
  755. close(0);
  756. if (open(_PATH_DEVNULL, O_RDONLY) != 0)
  757. error("cannot open %s: %s",
  758. _PATH_DEVNULL, strerror(errno));
  759. }
  760. }
  761. #else
  762. if (mode == FORK_BG) {
  763. ignoresig(SIGINT);
  764. ignoresig(SIGQUIT);
  765. if ((jp == NULL || jp->nprocs == 0) &&
  766. ! fd0_redirected_p ()) {
  767. close(0);
  768. if (open(_PATH_DEVNULL, O_RDONLY) != 0)
  769. error("cannot open %s: %s",
  770. _PATH_DEVNULL, strerror(errno));
  771. }
  772. }
  773. #endif
  774. INTOFF;
  775. for (i = njobs, p = jobtab ; --i >= 0 ; p++)
  776. if (p->used)
  777. freejob(p);
  778. INTON;
  779. if (wasroot && iflag) {
  780. setsignal(SIGINT);
  781. setsignal(SIGQUIT);
  782. setsignal(SIGTERM);
  783. }
  784. return pid;
  785. }
  786. if (rootshell && mode != FORK_NOJOB && mflag) {
  787. if (jp == NULL || jp->nprocs == 0)
  788. pgrp = pid;
  789. else
  790. pgrp = jp->ps[0].pid;
  791. setpgid(pid, pgrp);
  792. }
  793. if (mode == FORK_BG) {
  794. if (bgjob != NULL && bgjob->state == JOBDONE &&
  795. !bgjob->remembered && !iflag)
  796. freejob(bgjob);
  797. backgndpid = pid; /* set $! */
  798. bgjob = jp;
  799. }
  800. if (jp) {
  801. struct procstat *ps = &jp->ps[jp->nprocs++];
  802. ps->pid = pid;
  803. ps->status = -1;
  804. ps->cmd = nullstr;
  805. if (iflag && rootshell && n)
  806. ps->cmd = commandtext(n);
  807. jp->foreground = mode == FORK_FG;
  808. #if JOBS
  809. setcurjob(jp);
  810. #endif
  811. }
  812. INTON;
  813. TRACE(("In parent shell: child = %d\n", (int)pid));
  814. return pid;
  815. }
  816. pid_t
  817. vforkexecshell(struct job *jp, char **argv, char **envp, const char *path, int idx, int pip[2])
  818. {
  819. pid_t pid;
  820. struct jmploc jmploc;
  821. struct jmploc *savehandler;
  822. TRACE(("vforkexecshell(%%%td, %p, %d) called\n", jp - jobtab, (void *)n,
  823. mode));
  824. INTOFF;
  825. flushall();
  826. savehandler = handler;
  827. pid = vfork();
  828. if (pid == -1) {
  829. TRACE(("Vfork failed, errno=%d\n", errno));
  830. INTON;
  831. error("Cannot fork: %s", strerror(errno));
  832. }
  833. if (pid == 0) {
  834. TRACE(("Child shell %d\n", (int)getpid()));
  835. if (setjmp(jmploc.loc))
  836. _exit(exception == EXEXEC ? exerrno : 2);
  837. if (pip != NULL) {
  838. close(pip[0]);
  839. if (pip[1] != 1) {
  840. dup2(pip[1], 1);
  841. close(pip[1]);
  842. }
  843. }
  844. handler = &jmploc;
  845. shellexec(argv, envp, path, idx);
  846. }
  847. handler = savehandler;
  848. if (jp) {
  849. struct procstat *ps = &jp->ps[jp->nprocs++];
  850. ps->pid = pid;
  851. ps->status = -1;
  852. ps->cmd = nullstr;
  853. jp->foreground = 1;
  854. #if JOBS
  855. setcurjob(jp);
  856. #endif
  857. }
  858. INTON;
  859. TRACE(("In parent shell: child = %d\n", (int)pid));
  860. return pid;
  861. }
  862. /*
  863. * Wait for job to finish.
  864. *
  865. * Under job control we have the problem that while a child process is
  866. * running interrupts generated by the user are sent to the child but not
  867. * to the shell. This means that an infinite loop started by an inter-
  868. * active user may be hard to kill. With job control turned off, an
  869. * interactive user may place an interactive program inside a loop. If
  870. * the interactive program catches interrupts, the user doesn't want
  871. * these interrupts to also abort the loop. The approach we take here
  872. * is to have the shell ignore interrupt signals while waiting for a
  873. * foreground process to terminate, and then send itself an interrupt
  874. * signal if the child process was terminated by an interrupt signal.
  875. * Unfortunately, some programs want to do a bit of cleanup and then
  876. * exit on interrupt; unless these processes terminate themselves by
  877. * sending a signal to themselves (instead of calling exit) they will
  878. * confuse this approach.
  879. */
  880. int
  881. waitforjob(struct job *jp, int *origstatus)
  882. {
  883. #if JOBS
  884. pid_t mypgrp = getpgrp();
  885. int propagate_int = jp->jobctl && jp->foreground;
  886. #endif
  887. int status;
  888. int st;
  889. INTOFF;
  890. TRACE(("waitforjob(%%%td) called\n", jp - jobtab + 1));
  891. while (jp->state == 0)
  892. if (dowait(1, jp) == -1)
  893. dotrap();
  894. #if JOBS
  895. if (jp->jobctl) {
  896. if (tcsetpgrp(ttyfd, mypgrp) < 0)
  897. error("tcsetpgrp failed, errno=%d\n", errno);
  898. }
  899. if (jp->state == JOBSTOPPED)
  900. setcurjob(jp);
  901. #endif
  902. status = jp->ps[jp->nprocs - 1].status;
  903. if (origstatus != NULL)
  904. *origstatus = status;
  905. /* convert to 8 bits */
  906. if (WIFEXITED(status))
  907. st = WEXITSTATUS(status);
  908. #if JOBS
  909. else if (WIFSTOPPED(status))
  910. st = WSTOPSIG(status) + 128;
  911. #endif
  912. else
  913. st = WTERMSIG(status) + 128;
  914. if (! JOBS || jp->state == JOBDONE)
  915. freejob(jp);
  916. if (int_pending()) {
  917. if (!WIFSIGNALED(status) || WTERMSIG(status) != SIGINT)
  918. CLEAR_PENDING_INT;
  919. }
  920. #if JOBS
  921. else if (rootshell && iflag && propagate_int &&
  922. WIFSIGNALED(status) && WTERMSIG(status) == SIGINT)
  923. kill(getpid(), SIGINT);
  924. #endif
  925. INTON;
  926. return st;
  927. }
  928. /*
  929. * Wait for a process to terminate.
  930. */
  931. static pid_t
  932. dowait(int block, struct job *job)
  933. {
  934. pid_t pid;
  935. int status;
  936. struct procstat *sp;
  937. struct job *jp;
  938. struct job *thisjob;
  939. int done;
  940. int stopped;
  941. int sig;
  942. int coredump;
  943. in_dowait++;
  944. TRACE(("dowait(%d) called\n", block));
  945. do {
  946. pid = waitproc(block, &status);
  947. TRACE(("wait returns %d, status=%d\n", (int)pid, status));
  948. } while ((pid == -1 && errno == EINTR && breakwaitcmd == 0) ||
  949. (pid > 0 && WIFSTOPPED(status) && !iflag));
  950. in_dowait--;
  951. if (pid == -1 && errno == ECHILD && job != NULL)
  952. job->state = JOBDONE;
  953. if (breakwaitcmd != 0) {
  954. breakwaitcmd = 0;
  955. if (pid <= 0)
  956. return -1;
  957. }
  958. if (pid <= 0)
  959. return pid;
  960. INTOFF;
  961. thisjob = NULL;
  962. for (jp = jobtab ; jp < jobtab + njobs ; jp++) {
  963. if (jp->used && jp->nprocs > 0) {
  964. done = 1;
  965. stopped = 1;
  966. for (sp = jp->ps ; sp < jp->ps + jp->nprocs ; sp++) {
  967. if (sp->pid == -1)
  968. continue;
  969. if (sp->pid == pid) {
  970. TRACE(("Changing status of proc %d from 0x%x to 0x%x\n",
  971. (int)pid, sp->status,
  972. status));
  973. sp->status = status;
  974. thisjob = jp;
  975. }
  976. if (sp->status == -1)
  977. stopped = 0;
  978. else if (WIFSTOPPED(sp->status))
  979. done = 0;
  980. }
  981. if (stopped) { /* stopped or done */
  982. int state = done? JOBDONE : JOBSTOPPED;
  983. if (jp->state != state) {
  984. TRACE(("Job %td: changing state from %d to %d\n", jp - jobtab + 1, jp->state, state));
  985. jp->state = state;
  986. if (jp != job) {
  987. if (done && !jp->remembered &&
  988. !iflag && jp != bgjob)
  989. freejob(jp);
  990. #if JOBS
  991. else if (done)
  992. deljob(jp);
  993. #endif
  994. }
  995. }
  996. }
  997. }
  998. }
  999. INTON;
  1000. if (!thisjob || thisjob->state == 0)
  1001. ;
  1002. else if ((!rootshell || !iflag || thisjob == job) &&
  1003. thisjob->foreground && thisjob->state != JOBSTOPPED) {
  1004. sig = 0;
  1005. coredump = 0;
  1006. for (sp = thisjob->ps; sp < thisjob->ps + thisjob->nprocs; sp++)
  1007. if (WIFSIGNALED(sp->status)) {
  1008. sig = WTERMSIG(sp->status);
  1009. coredump = WCOREDUMP(sp->status);
  1010. }
  1011. if (sig > 0 && sig != SIGINT && sig != SIGPIPE) {
  1012. if (sig < sys_nsig && sys_siglist[sig])
  1013. out2str(sys_siglist[sig]);
  1014. else
  1015. outfmt(out2, "Signal %d", sig);
  1016. if (coredump)
  1017. out2str(" (core dumped)");
  1018. out2c('\n');
  1019. flushout(out2);
  1020. }
  1021. } else {
  1022. TRACE(("Not printing status, rootshell=%d, job=%p\n", rootshell, job));
  1023. thisjob->changed = 1;
  1024. }
  1025. return pid;
  1026. }
  1027. /*
  1028. * Do a wait system call. If job control is compiled in, we accept
  1029. * stopped processes. If block is zero, we return a value of zero
  1030. * rather than blocking.
  1031. */
  1032. static pid_t
  1033. waitproc(int block, int *status)
  1034. {
  1035. int flags;
  1036. #if JOBS
  1037. flags = WUNTRACED;
  1038. #else
  1039. flags = 0;
  1040. #endif
  1041. if (block == 0)
  1042. flags |= WNOHANG;
  1043. return wait3(status, flags, (struct rusage *)NULL);
  1044. }
  1045. /*
  1046. * return 1 if there are stopped jobs, otherwise 0
  1047. */
  1048. int job_warning = 0;
  1049. int
  1050. stoppedjobs(void)
  1051. {
  1052. int jobno;
  1053. struct job *jp;
  1054. if (job_warning)
  1055. return (0);
  1056. for (jobno = 1, jp = jobtab; jobno <= njobs; jobno++, jp++) {
  1057. if (jp->used == 0)
  1058. continue;
  1059. if (jp->state == JOBSTOPPED) {
  1060. out2fmt_flush("You have stopped jobs.\n");
  1061. job_warning = 2;
  1062. return (1);
  1063. }
  1064. }
  1065. return (0);
  1066. }
  1067. static void
  1068. checkzombies(void)
  1069. {
  1070. while (njobs > 0 && dowait(0, NULL) > 0)
  1071. ;
  1072. }
  1073. int
  1074. backgndpidset(void)
  1075. {
  1076. return backgndpid != -1;
  1077. }
  1078. pid_t
  1079. backgndpidval(void)
  1080. {
  1081. if (bgjob != NULL && !forcelocal)
  1082. bgjob->remembered = 1;
  1083. return backgndpid;
  1084. }
  1085. /*
  1086. * Return a string identifying a command (to be printed by the
  1087. * jobs command.
  1088. */
  1089. static char *cmdnextc;
  1090. static int cmdnleft;
  1091. #define MAXCMDTEXT 200
  1092. char *
  1093. commandtext(union node *n)
  1094. {
  1095. char *name;
  1096. cmdnextc = name = ckmalloc(MAXCMDTEXT);
  1097. cmdnleft = MAXCMDTEXT - 4;
  1098. cmdtxt(n);
  1099. *cmdnextc = '\0';
  1100. return name;
  1101. }
  1102. static void
  1103. cmdtxt(union node *n)
  1104. {
  1105. union node *np;
  1106. struct nodelist *lp;
  1107. const char *p;
  1108. int i;
  1109. char s[2];
  1110. if (n == NULL)
  1111. return;
  1112. switch (n->type) {
  1113. case NSEMI:
  1114. cmdtxt(n->nbinary.ch1);
  1115. cmdputs("; ");
  1116. cmdtxt(n->nbinary.ch2);
  1117. break;
  1118. case NAND:
  1119. cmdtxt(n->nbinary.ch1);
  1120. cmdputs(" && ");
  1121. cmdtxt(n->nbinary.ch2);
  1122. break;
  1123. case NOR:
  1124. cmdtxt(n->nbinary.ch1);
  1125. cmdputs(" || ");
  1126. cmdtxt(n->nbinary.ch2);
  1127. break;
  1128. case NPIPE:
  1129. for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
  1130. cmdtxt(lp->n);
  1131. if (lp->next)
  1132. cmdputs(" | ");
  1133. }
  1134. break;
  1135. case NSUBSHELL:
  1136. cmdputs("(");
  1137. cmdtxt(n->nredir.n);
  1138. cmdputs(")");
  1139. break;
  1140. case NREDIR:
  1141. case NBACKGND:
  1142. cmdtxt(n->nredir.n);
  1143. break;
  1144. case NIF:
  1145. cmdputs("if ");
  1146. cmdtxt(n->nif.test);
  1147. cmdputs("; then ");
  1148. cmdtxt(n->nif.ifpart);
  1149. cmdputs("...");
  1150. break;
  1151. case NWHILE:
  1152. cmdputs("while ");
  1153. goto until;
  1154. case NUNTIL:
  1155. cmdputs("until ");
  1156. until:
  1157. cmdtxt(n->nbinary.ch1);
  1158. cmdputs("; do ");
  1159. cmdtxt(n->nbinary.ch2);
  1160. cmdputs("; done");
  1161. break;
  1162. case NFOR:
  1163. cmdputs("for ");
  1164. cmdputs(n->nfor.var);
  1165. cmdputs(" in ...");
  1166. break;
  1167. case NCASE:
  1168. cmdputs("case ");
  1169. cmdputs(n->ncase.expr->narg.text);
  1170. cmdputs(" in ...");
  1171. break;
  1172. case NDEFUN:
  1173. cmdputs(n->narg.text);
  1174. cmdputs("() ...");
  1175. break;
  1176. case NCMD:
  1177. for (np = n->ncmd.args ; np ; np = np->narg.next) {
  1178. cmdtxt(np);
  1179. if (np->narg.next)
  1180. cmdputs(" ");
  1181. }
  1182. for (np = n->ncmd.redirect ; np ; np = np->nfile.next) {
  1183. cmdputs(" ");
  1184. cmdtxt(np);
  1185. }
  1186. break;
  1187. case NARG:
  1188. cmdputs(n->narg.text);
  1189. break;
  1190. case NTO:
  1191. p = ">"; i = 1; goto redir;
  1192. case NAPPEND:
  1193. p = ">>"; i = 1; goto redir;
  1194. case NTOFD:
  1195. p = ">&"; i = 1; goto redir;
  1196. case NCLOBBER:
  1197. p = ">|"; i = 1; goto redir;
  1198. case NFROM:
  1199. p = "<"; i = 0; goto redir;
  1200. case NFROMTO:
  1201. p = "<>"; i = 0; goto redir;
  1202. case NFROMFD:
  1203. p = "<&"; i = 0; goto redir;
  1204. redir:
  1205. if (n->nfile.fd != i) {
  1206. s[0] = n->nfile.fd + '0';
  1207. s[1] = '\0';
  1208. cmdputs(s);
  1209. }
  1210. cmdputs(p);
  1211. if (n->type == NTOFD || n->type == NFROMFD) {
  1212. if (n->ndup.dupfd >= 0)
  1213. s[0] = n->ndup.dupfd + '0';
  1214. else
  1215. s[0] = '-';
  1216. s[1] = '\0';
  1217. cmdputs(s);
  1218. } else {
  1219. cmdtxt(n->nfile.fname);
  1220. }
  1221. break;
  1222. case NHERE:
  1223. case NXHERE:
  1224. cmdputs("<<...");
  1225. break;
  1226. default:
  1227. cmdputs("???");
  1228. break;
  1229. }
  1230. }
  1231. static void
  1232. cmdputs(const char *s)
  1233. {
  1234. const char *p;
  1235. char *q;
  1236. char c;
  1237. int subtype = 0;
  1238. if (cmdnleft <= 0)
  1239. return;
  1240. p = s;
  1241. q = cmdnextc;
  1242. while ((c = *p++) != '\0') {
  1243. if (c == CTLESC)
  1244. *q++ = *p++;
  1245. else if (c == CTLVAR) {
  1246. *q++ = '$';
  1247. if (--cmdnleft > 0)
  1248. *q++ = '{';
  1249. subtype = *p++;
  1250. if ((subtype & VSTYPE) == VSLENGTH && --cmdnleft > 0)
  1251. *q++ = '#';
  1252. } else if (c == '=' && subtype != 0) {
  1253. *q = "}-+?=##%%\0X"[(subtype & VSTYPE) - VSNORMAL];
  1254. if (*q)
  1255. q++;
  1256. else
  1257. cmdnleft++;
  1258. if (((subtype & VSTYPE) == VSTRIMLEFTMAX ||
  1259. (subtype & VSTYPE) == VSTRIMRIGHTMAX) &&
  1260. --cmdnleft > 0)
  1261. *q = q[-1], q++;
  1262. subtype = 0;
  1263. } else if (c == CTLENDVAR) {
  1264. *q++ = '}';
  1265. } else if (c == CTLBACKQ || c == CTLBACKQ+CTLQUOTE) {
  1266. cmdnleft -= 5;
  1267. if (cmdnleft > 0) {
  1268. *q++ = '$';
  1269. *q++ = '(';
  1270. *q++ = '.';
  1271. *q++ = '.';
  1272. *q++ = '.';
  1273. *q++ = ')';
  1274. }
  1275. } else if (c == CTLARI) {
  1276. cmdnleft -= 2;
  1277. if (cmdnleft > 0) {
  1278. *q++ = '$';
  1279. *q++ = '(';
  1280. *q++ = '(';
  1281. }
  1282. p++;
  1283. } else if (c == CTLENDARI) {
  1284. if (--cmdnleft > 0) {
  1285. *q++ = ')';
  1286. *q++ = ')';
  1287. }
  1288. } else if (c == CTLQUOTEMARK || c == CTLQUOTEEND)
  1289. cmdnleft++; /* ignore */
  1290. else
  1291. *q++ = c;
  1292. if (--cmdnleft <= 0) {
  1293. *q++ = '.';
  1294. *q++ = '.';
  1295. *q++ = '.';
  1296. break;
  1297. }
  1298. }
  1299. cmdnextc = q;
  1300. }