home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / gnustuff / tos / bash / bash-108 / bash-108.zoo / src / nojobs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-09-12  |  8.7 KB  |  392 lines

  1. /* The thing that makes children, remembers them, and contains wait loops. */
  2.  
  3. /* This file works under BSD, System V, minix, and Posix systems. */
  4.  
  5. /* Copyright (C) 1987,1989 Free Software Foundation, Inc.
  6.  
  7. This file is part of GNU Bash, the Bourne Again SHell.
  8.  
  9. Bash is free software; you can redistribute it and/or modify it under
  10. the terms of the GNU General Public License as published by the Free
  11. Software Foundation; either version 1, or (at your option) any later
  12. version.
  13.  
  14. Bash is distributed in the hope that it will be useful, but WITHOUT ANY
  15. WARRANTY; without even the implied warranty of MERCHANTABILITY or
  16. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  17. for more details.
  18.  
  19. You should have received a copy of the GNU General Public License along
  20. with Bash; see the file COPYING.  If not, write to the Free Software
  21. Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
  22.  
  23. #include <stdio.h>
  24. #include <sys/types.h>
  25. #include <fcntl.h>
  26. #include <signal.h>
  27. #include <setjmp.h>
  28. #include <errno.h>
  29.  
  30. #include "config.h"
  31. #include "general.h"
  32. #include "jobs.h"
  33.  
  34. #if !defined (USG) && !defined (_POSIX_VERSION)
  35. #  include <sgtty.h>
  36. #else
  37. #  if defined (USG)
  38. #    include <termio.h>
  39. #    include <sys/ttold.h>
  40. #  else 
  41. #    include <termios.h>
  42. #  endif
  43. #endif /* !USG && !_POSIX_VERSION */
  44.  
  45. #ifndef SIGABRT
  46. #define SIGABRT SIGIOT
  47. #endif
  48.  
  49. /**
  50.  ** (sjk)++ Remove all host/mail references on the Atari ST1
  51.  **/
  52. #if defined (USG) || defined (_POSIX_VERSION) || defined(atarist)
  53. #define killpg(pg, sig)        kill(-(pg),(sig))
  54. #endif
  55.  
  56. /**
  57.  ** (sjk)++ Make siginterrupt() a NULL code on the Atari ST
  58.  **/
  59. #if defined (USG) || defined(atarist)
  60. #define siginterrupt(sig, code)
  61. #endif
  62.  
  63. pid_t last_made_pid = (pid_t)-1;
  64. pid_t last_asynchronous_pid = (pid_t)-1;
  65.  
  66. extern int errno;
  67.  
  68. /* Initialize the job control mechanism, and set up the tty stuff. */
  69. initialize_jobs ()
  70. {
  71.   get_tty_state ();
  72. }
  73.  
  74. /* Setup this shell to handle C-C, etc. */
  75. initialize_job_signals ()
  76. {
  77.   extern int login_shell;
  78.   extern sighandler sigint_sighandler ();
  79.  
  80.   signal (SIGINT, sigint_sighandler);
  81.   signal (SIGQUIT, SIG_IGN);
  82.  
  83.   /* If this is a login shell we don't wish to be disturbed by
  84.      stop signals. */
  85.   if (login_shell)
  86.     {
  87. #ifdef SIGTSTP
  88.       signal (SIGTSTP, SIG_IGN);
  89.       signal (SIGTTOU, SIG_IGN);
  90.       signal (SIGTTIN, SIG_IGN);
  91. #endif
  92.     }
  93. }
  94.  
  95. /* Fork, handling errors.  Returns the pid of the newly made child, or 0.
  96.    COMMAND is just for remembering the name of the command; we don't do
  97.    anything else with it.  ASYNC_P says what to do with the tty.  If
  98.    non-zero, then don't give it away. */
  99. pid_t
  100. make_child (command, async_p)
  101.      char *command;
  102.      int async_p;
  103. {
  104.   pid_t pid;
  105.  
  106.   /* Discard saved memory. */
  107.   if (command)  
  108.     free (command);
  109.  
  110.   /* Make new environment array if neccessary. */
  111.   maybe_make_export_env ();
  112.  
  113.   /* Create the child, handle severe errors. */
  114.   if ((pid = fork ()) < 0)
  115.     {
  116.       report_error ("fork: %s", strerror (errno));
  117.  
  118.       throw_to_top_level ();
  119.     }
  120.  
  121.   if (!pid)
  122.     {
  123.       /* Ignore INT and QUIT in asynchronous children. */
  124.       if (async_p)
  125.     {
  126.       signal (SIGINT, SIG_IGN);
  127.       signal (SIGQUIT, SIG_IGN);
  128.       last_asynchronous_pid = getpid ();
  129.     }
  130.       else
  131.     {
  132.       restore_default_signal (SIGINT);
  133.       restore_default_signal (SIGQUIT);
  134.  
  135. #if defined (SIGTSTP)
  136.       signal (SIGTSTP, SIG_DFL);
  137.       signal (SIGTTIN, SIG_DFL);
  138.       signal (SIGTTOU, SIG_DFL);
  139. #endif
  140.  
  141.       restore_original_signals ();     /* cancel traps, in trap.c */
  142.     }
  143.  
  144.       /* Children are easily terminated with SIGTERM. */
  145.       restore_default_signal (SIGTERM);
  146.     }
  147.   else
  148.     {
  149.       /*
  150.        * In the parent.
  151.        */
  152.       last_made_pid = pid;
  153.  
  154.       if (async_p)
  155.     last_asynchronous_pid = pid;
  156.     }
  157.   return (pid);
  158. }
  159.  
  160. /**
  161.  ** (sjk)++ Define ECHILD to be an unknown/general ERROR code for the Atari ST
  162.  **/
  163. #if defined(atarist)
  164. #define ECHILD (-1)
  165. #endif
  166.  
  167. /* Wait for a single pid (PID) and return its exit status. */
  168.  
  169. wait_for_single_pid (pid)
  170.      pid_t pid;
  171. {
  172.   pid_t got_pid;
  173.   WAIT status;
  174.  
  175.   siginterrupt (SIGINT, 1);
  176.   while ((got_pid = wait (&status)) != pid)
  177.     {
  178.       if (got_pid < 0)
  179.     {
  180.       if (errno != EINTR && errno != ECHILD)
  181.         {
  182.           siginterrupt (SIGINT, 0);
  183.           file_error ("wait");
  184.         }
  185.       break;
  186.     }
  187.     }
  188.   siginterrupt (SIGINT, 0);
  189.   QUIT;
  190. }
  191.  
  192. /* Wait for all of the shell's children to exit. */
  193.  
  194. wait_for_background_pids ()
  195. {
  196.   /* If we aren't using job control, we let the kernel take care of the
  197.      bookkeeping for us.  wait () will return -1 and set errno to ECHILD 
  198.      when there are no more unwaited-for child processes on both
  199.      4.2 BSD-based and System V-based systems. */
  200.  
  201.   siginterrupt (SIGINT, 1);
  202.   while (1)
  203.     {
  204.       pid_t got_pid;
  205.       WAIT status;
  206.  
  207.       while ((got_pid = wait(&status)) != -1)  /* wait for ECHILD */
  208.      printf("Stuck in wait loop with got_pid = %d\n",got_pid);
  209.  
  210.       if (errno != EINTR && errno != ECHILD)
  211.     {
  212.       siginterrupt (SIGINT, 0);
  213.       file_error("wait");
  214.     }
  215.       break;
  216.     }
  217.   siginterrupt (SIGINT, 0);
  218.   QUIT;
  219. }
  220.  
  221. /* Wait for pid (one of our children) to terminate. */
  222. int
  223. wait_for (pid)
  224.      pid_t pid;
  225. {
  226.   extern int interactive;
  227.   int return_val;
  228.   pid_t got_pid;
  229.   WAIT status;
  230.  
  231.   /* Make sure that the process we are waiting for is valid. */
  232.   if ((kill (pid, 0) < 0) && (errno == ESRCH))
  233.     return (0);
  234.  
  235.   siginterrupt (SIGINT, 1);
  236.   while ((got_pid = wait (&status)) != pid)
  237.     {
  238.       if (got_pid < 0 && errno == ECHILD)
  239.     {
  240. #if !defined (_POSIX_VERSION)
  241.       status.w_termsig = status.w_retcode = 0;
  242. #else
  243.       status = 0;
  244. #endif /* _POSIX_VERSION */
  245.       break;
  246.     }
  247.       else if (got_pid < 0 && errno != EINTR)
  248.     programming_error ("got errno %d while waiting for %d", errno, pid);
  249.     }
  250.   siginterrupt (SIGINT, 0);
  251.  
  252. #if 0
  253.   /* Not needed because the builtin wait does not go through this path. */
  254.   if (interactive)    /* allow the user to ^C out of the builtin wait */
  255.     QUIT;
  256. #endif
  257.  
  258.   /* Default return value. */
  259.   /* ``a full 8 bits of status is returned'' */
  260.   if (WIFSIGNALED (status))
  261.     return_val = 128 + WTERMSIG (status);
  262.   else
  263.     return_val = WEXITSTATUS (status);
  264.                             
  265.   if (!WIFSTOPPED (status) && WIFSIGNALED (status) &&
  266.       (WTERMSIG (status) != SIGINT))
  267.     {
  268.       extern char *sys_siglist[];
  269.       fprintf (stderr, "%s", sys_siglist[WTERMSIG (status)]);
  270.       if (WIFCORED (status))
  271.     fprintf (stderr, " (core dumped)");
  272.       fprintf (stderr, "\n");
  273.     }
  274.  
  275.   if (WIFSIGNALED (status) || WIFSTOPPED (status))
  276.     set_tty_state ();
  277.   else
  278.     get_tty_state ();
  279.                             
  280.   return (return_val);
  281. }
  282.  
  283. /* Give PID SIGNAL.  This determines what job the pid belongs to (if any).
  284.    If PID does belong to a job, and the job is stopped, then CONTinue the
  285.    job after giving it SIGNAL.  Returns -1 on failure.  If GROUP is non-null,
  286.    then kill the process group associated with PID. */
  287. int
  288. kill_pid (pid, signal, group)
  289.      pid_t pid;
  290.      int signal, group;
  291. {
  292.   int result;
  293.  
  294.   if (group)
  295.     result = killpg (pid, signal);
  296.   else
  297.     result = kill (pid, signal);
  298.  
  299.   return (result);
  300. }
  301.  
  302. #if defined (_POSIX_VERSION)
  303. static struct termios shell_tty_info;
  304. #else
  305. #  if defined (USG)
  306. static struct termio shell_tty_info;
  307. #  else
  308. static struct sgttyb shell_tty_info;
  309. #  endif /* USG */
  310. #endif /* _POSIX_VERSION */
  311.  
  312. static int got_tty_state = 0;
  313.  
  314. /* Fill the contents of shell_tty_info with the current tty info. */
  315. get_tty_state ()
  316. {
  317. /**
  318.  ** (sjk)++ Attach the terminal to CON: on the Atari ST
  319.  **/
  320. #if !defined(atarist)
  321.   int tty = open ("/dev/tty", O_RDONLY);
  322. #else 
  323.   int tty = open("CON:", O_RDONLY);
  324. #endif 
  325.   if (tty != -1)
  326.     {
  327.    
  328. #if defined (_POSIX_VERSION)
  329.       tcgetattr (tty, &shell_tty_info);
  330. #else
  331. #  if defined (USG)
  332.       ioctl (tty, TCGETA, &shell_tty_info);
  333. #  else
  334.       ioctl (tty, TIOCGETP, &shell_tty_info);
  335. #  endif
  336. #endif
  337.       close (tty);
  338.       got_tty_state = 1;
  339.     }
  340. }
  341.  
  342. /* Make the current tty use the state in shell_tty_info. */
  343. set_tty_state ()
  344. {
  345. /**
  346.  ** (sjk)++ Attach the terminal to CON: on the Atari ST
  347.  **/
  348. #if !defined(atarist)
  349.   int tty = open ("/dev/tty", O_RDONLY);
  350. #else 
  351.   int tty = open("CON:", O_RDONLY);
  352. #endif 
  353.   if (tty != -1)
  354.     {
  355.       if (!got_tty_state)
  356.         return;
  357. #if defined (_POSIX_VERSION)
  358.       tcsetattr (tty, TCSADRAIN, &shell_tty_info);
  359. #else
  360. /** 
  361.  ** (sjk)++ Set the terminal parameters ala USG if on an Atari ST
  362.  **/
  363. #if defined (USG) || defined(atarist)
  364.       ioctl (tty, TIOCSETN, &shell_tty_info);
  365. #else
  366.       ioctl (tty, TCSETAW, &shell_tty_info);  /* Wait for output, no flush */
  367. #endif
  368. #endif
  369.       close (tty);
  370.     }
  371. }
  372.  
  373. /* Give the terminal to PGRP.  */
  374. give_terminal_to (pgrp)
  375.      pid_t pgrp;
  376. {
  377. }
  378.  
  379. /* Stop a pipeline. */
  380. stop_pipeline (async, ignore)
  381.      int async;
  382.      char *ignore;
  383. {
  384. }
  385.  
  386. /* Print descriptive information about the job with leader pid PID. */
  387. describe_pid (pid)
  388.      pid_t pid;
  389. {
  390.   fprintf (stderr, "<%d>\n", (int) pid);
  391. }
  392.