PageRenderTime 63ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/bin/sh/jobs.c

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