source: trunk/third/bash/nojobs.c @ 18290

Revision 18290, 20.3 KB checked in by zacheiss, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18289, which included commits to RCS files with non-trunk default branches.
Line 
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.  It does
4   not implement job control. */
5
6/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
7
8   This file is part of GNU Bash, the Bourne Again SHell.
9
10   Bash is free software; you can redistribute it and/or modify it under
11   the terms of the GNU General Public License as published by the Free
12   Software Foundation; either version 2, or (at your option) any later
13   version.
14
15   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
16   WARRANTY; without even the implied warranty of MERCHANTABILITY or
17   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
18   for more details.
19
20   You should have received a copy of the GNU General Public License along
21   with Bash; see the file COPYING.  If not, write to the Free Software
22   Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
23
24#include "config.h"
25
26#include "bashtypes.h"
27#include "filecntl.h"
28
29#if defined (HAVE_UNISTD_H)
30#  include <unistd.h>
31#endif
32
33#include <stdio.h>
34#include <signal.h>
35#include <errno.h>
36
37#if defined (BUFFERED_INPUT)
38#  include "input.h"
39#endif
40
41/* Need to include this up here for *_TTY_DRIVER definitions. */
42#include "shtty.h"
43
44#if !defined (STRUCT_WINSIZE_IN_SYS_IOCTL)
45/* For struct winsize on SCO */
46/*   sys/ptem.h has winsize but needs mblk_t from sys/stream.h */
47#  if defined (HAVE_SYS_PTEM_H) && defined (TIOCGWINSZ) && defined (SIGWINCH)
48#    if defined (HAVE_SYS_STREAM_H)
49#      include <sys/stream.h>
50#    endif
51#    include <sys/ptem.h>
52#  endif /* HAVE_SYS_PTEM_H && TIOCGWINSZ && SIGWINCH */
53#endif /* !STRUCT_WINSIZE_IN_SYS_IOCTL */
54
55#include "shell.h"
56#include "jobs.h"
57
58#include "builtins/builtext.h"  /* for wait_builtin */
59
60#define DEFAULT_CHILD_MAX 32
61
62#if defined (_POSIX_VERSION) || !defined (HAVE_KILLPG)
63#  define killpg(pg, sig)               kill(-(pg),(sig))
64#endif /* USG || _POSIX_VERSION */
65
66#if !defined (HAVE_SIGINTERRUPT)
67#  define siginterrupt(sig, code)
68#endif /* !HAVE_SIGINTERRUPT */
69
70#if defined (HAVE_WAITPID)
71#  define WAITPID(pid, statusp, options) waitpid (pid, statusp, options)
72#else
73#  define WAITPID(pid, statusp, options) wait (statusp)
74#endif /* !HAVE_WAITPID */
75
76/* Return the fd from which we are actually getting input. */
77#define input_tty() (shell_tty != -1) ? shell_tty : fileno (stderr)
78
79#if !defined (errno)
80extern int errno;
81#endif /* !errno */
82
83#if defined (READLINE)
84extern void rl_set_screen_size __P((int, int));
85#endif
86
87extern int interactive, interactive_shell, login_shell;
88extern int subshell_environment;
89extern int last_command_exit_value;
90extern int interrupt_immediately;
91extern sh_builtin_func_t *this_shell_builtin;
92#if defined (HAVE_POSIX_SIGNALS)
93extern sigset_t top_level_mask;
94#endif
95extern procenv_t wait_intr_buf;
96extern int wait_signal_received;
97
98pid_t last_made_pid = NO_PID;
99pid_t last_asynchronous_pid = NO_PID;
100
101/* Call this when you start making children. */
102int already_making_children = 0;
103
104/* The controlling tty for this shell. */
105int shell_tty = -1;
106
107/* If this is non-zero, $LINES and $COLUMNS are reset after every process
108   exits from get_tty_state(). */
109int check_window_size;
110
111/* STATUS and FLAGS are only valid if pid != NO_PID
112   STATUS is only valid if (flags & PROC_RUNNING) == 0 */
113struct proc_status {
114  pid_t pid;
115  int status;   /* Exit status of PID or 128 + fatal signal number */
116  int flags;
117};
118
119/* Values for proc_status.flags */
120#define PROC_RUNNING    0x01
121#define PROC_NOTIFIED   0x02
122#define PROC_ASYNC      0x04
123
124/* Return values from find_status_by_pid */
125#define PROC_BAD         -1
126#define PROC_STILL_ALIVE -2
127
128static struct proc_status *pid_list = (struct proc_status *)NULL;
129static int pid_list_size;
130static int wait_sigint_received;
131
132static long child_max = -1L;
133
134static void alloc_pid_list __P((void));
135static int find_proc_slot __P((void));
136static int find_index_by_pid __P((pid_t));
137static int find_status_by_pid __P((pid_t));
138static int process_exit_status __P((WAIT));
139static void set_pid_status __P((pid_t, WAIT));
140static void set_pid_flags __P((pid_t, int));
141static void unset_pid_flags __P((pid_t, int));
142static void add_pid __P((pid_t, int));
143static void mark_dead_jobs_as_notified __P((int));
144
145static void get_new_window_size __P((int));
146static sighandler sigwinch_sighandler __P((int));
147static sighandler wait_sigint_handler __P((int));
148
149#if defined (HAVE_WAITPID)
150static void reap_zombie_children __P((void));
151#endif
152
153static void restore_sigint_handler __P((void));
154
155/* Allocate new, or grow existing PID_LIST. */
156static void
157alloc_pid_list ()
158{
159  register int i;
160  int old = pid_list_size;
161
162  pid_list_size += 10;
163  pid_list = (struct proc_status *)xrealloc (pid_list, pid_list_size * sizeof (struct proc_status));
164
165  /* None of the newly allocated slots have process id's yet. */
166  for (i = old; i < pid_list_size; i++)
167    pid_list[i].pid = NO_PID;
168}
169
170/* Return the offset within the PID_LIST array of an empty slot.  This can
171   create new slots if all of the existing slots are taken. */
172static int
173find_proc_slot ()
174{
175  register int i;
176
177  for (i = 0; i < pid_list_size; i++)
178    if (pid_list[i].pid == NO_PID)
179      return (i);
180
181  if (i == pid_list_size)
182    alloc_pid_list ();
183
184  return (i);
185}
186
187/* Return the offset within the PID_LIST array of a slot containing PID,
188   or the value NO_PID if the pid wasn't found. */
189static int
190find_index_by_pid (pid)
191     pid_t pid;
192{
193  register int i;
194
195  for (i = 0; i < pid_list_size; i++)
196    if (pid_list[i].pid == pid)
197      return (i);
198
199  return (NO_PID);
200}
201
202/* Return the status of PID as looked up in the PID_LIST array.  A
203   return value of PROC_BAD indicates that PID wasn't found. */
204static int
205find_status_by_pid (pid)
206     pid_t pid;
207{
208  int i;
209
210  i = find_index_by_pid (pid);
211  if (i == NO_PID)
212    return (PROC_BAD);
213  if (pid_list[i].flags & PROC_RUNNING)
214    return (PROC_STILL_ALIVE);
215  return (pid_list[i].status);
216}
217
218static int
219process_exit_status (status)
220     WAIT status;
221{
222  if (WIFSIGNALED (status))
223    return (128 + WTERMSIG (status));
224  else
225    return (WEXITSTATUS (status));
226}
227
228/* Give PID the status value STATUS in the PID_LIST array. */
229static void
230set_pid_status (pid, status)
231     pid_t pid;
232     WAIT status;
233{
234  int slot;
235
236  slot = find_index_by_pid (pid);
237  if (slot == NO_PID)
238    return;
239
240  pid_list[slot].status = process_exit_status (status);
241  pid_list[slot].flags &= ~PROC_RUNNING;
242  /* If it's not a background process, mark it as notified so it gets
243     cleaned up. */
244  if ((pid_list[slot].flags & PROC_ASYNC) == 0)
245    pid_list[slot].flags |= PROC_NOTIFIED;
246}
247
248/* Give PID the flags FLAGS in the PID_LIST array. */
249static void
250set_pid_flags (pid, flags)
251     pid_t pid;
252     int flags;
253{
254  int slot;
255
256  slot = find_index_by_pid (pid);
257  if (slot == NO_PID)
258    return;
259
260  pid_list[slot].flags |= flags;
261}
262
263/* Unset FLAGS for PID in the pid list */
264static void
265unset_pid_flags (pid, flags)
266     pid_t pid;
267     int flags;
268{
269  int slot;
270
271  slot = find_index_by_pid (pid);
272  if (slot == NO_PID)
273    return;
274
275  pid_list[slot].flags &= ~flags;
276}
277
278static void
279add_pid (pid, async)
280     pid_t pid;
281     int async;
282{
283  int slot;
284
285  slot = find_proc_slot ();
286
287  pid_list[slot].pid = pid;
288  pid_list[slot].status = -1;
289  pid_list[slot].flags = PROC_RUNNING;
290  if (async)
291    pid_list[slot].flags |= PROC_ASYNC;
292}
293
294static void
295mark_dead_jobs_as_notified (force)
296     int force;
297{
298  register int i, ndead;
299
300  /* first, count the number of non-running async jobs if FORCE == 0 */
301  for (i = ndead = 0; force == 0 && i < pid_list_size; i++)
302    {
303      if (pid_list[i].pid == NO_PID)
304        continue;
305      if (((pid_list[i].flags & PROC_RUNNING) == 0) &&
306           (pid_list[i].flags & PROC_ASYNC))
307        ndead++;
308    }
309
310  if (child_max < 0)
311    child_max = getmaxchild ();
312  if (child_max < 0)
313    child_max = DEFAULT_CHILD_MAX;
314
315  if (force == 0 && ndead <= child_max)
316    return;
317
318  /* If FORCE == 0, we just mark as many non-running async jobs as notified
319     to bring us under the CHILD_MAX limit. */
320  for (i = 0; i < pid_list_size; i++)
321    {
322      if (pid_list[i].pid == NO_PID)
323        continue;
324      if (((pid_list[i].flags & PROC_RUNNING) == 0) &&
325           pid_list[i].pid != last_asynchronous_pid)
326        {
327          pid_list[i].flags |= PROC_NOTIFIED;
328          if (force == 0 && (pid_list[i].flags & PROC_ASYNC) && --ndead <= child_max)
329            break;
330        }
331    }
332}
333
334/* Remove all dead, notified jobs from the pid_list. */
335int
336cleanup_dead_jobs ()
337{
338  register int i;
339
340#if defined (HAVE_WAITPID)
341  reap_zombie_children ();
342#endif
343
344  for (i = 0; i < pid_list_size; i++)
345    {
346      if ((pid_list[i].flags & PROC_RUNNING) == 0 &&
347          (pid_list[i].flags & PROC_NOTIFIED))
348        pid_list[i].pid = NO_PID;
349    }
350
351  return 0;
352}
353
354void
355reap_dead_jobs ()
356{
357  mark_dead_jobs_as_notified (0);
358  cleanup_dead_jobs ();
359}
360
361/* Initialize the job control mechanism, and set up the tty stuff. */
362initialize_job_control (force)
363     int force;
364{
365  shell_tty = fileno (stderr);
366
367  if (interactive)
368    get_tty_state ();
369}
370
371#if defined (TIOCGWINSZ) && defined (SIGWINCH)
372static SigHandler *old_winch = (SigHandler *)SIG_DFL;
373
374static void
375get_new_window_size (from_sig)
376     int from_sig;
377{
378  struct winsize win;
379  int tty;
380
381  tty = input_tty ();
382  if (tty >= 0 && (ioctl (tty, TIOCGWINSZ, &win) == 0) &&
383      win.ws_row > 0 && win.ws_col > 0)
384    {
385#if defined (aixpc)
386      shell_tty_info.c_winsize = win;   /* structure copying */
387#endif
388      sh_set_lines_and_columns (win.ws_row, win.ws_col);
389#if defined (READLINE)
390      rl_set_screen_size (win.ws_row, win.ws_col);
391#endif
392    }
393}
394
395static sighandler
396sigwinch_sighandler (sig)
397     int sig;
398{
399#if defined (MUST_REINSTALL_SIGHANDLERS)
400  set_signal_handler (SIGWINCH, sigwinch_sighandler);
401#endif /* MUST_REINSTALL_SIGHANDLERS */
402  get_new_window_size (1);
403}
404#else
405static void
406get_new_window_size (from_sig)
407     int from_sig;
408{
409}
410#endif /* TIOCGWINSZ && SIGWINCH */
411
412void
413set_sigwinch_handler ()
414{
415#if defined (TIOCGWINSZ) && defined (SIGWINCH)
416  old_winch = set_signal_handler (SIGWINCH, sigwinch_sighandler);
417#endif
418}
419
420void
421unset_sigwinch_handler ()
422{
423#if defined (TIOCGWINSZ) && defined (SIGWINCH)
424  set_signal_handler (SIGWINCH, old_winch);
425#endif
426}
427
428/* Setup this shell to handle C-C, etc. */
429void
430initialize_job_signals ()
431{
432  set_signal_handler (SIGINT, sigint_sighandler);
433  set_sigwinch_handler ();
434
435  /* If this is a login shell we don't wish to be disturbed by
436     stop signals. */
437  if (login_shell)
438    ignore_tty_job_signals ();
439}
440
441#if defined (HAVE_WAITPID)
442/* Collect the status of all zombie children so that their system
443   resources can be deallocated. */
444static void
445reap_zombie_children ()
446{
447#if defined (WNOHANG)
448  pid_t pid;
449  WAIT status;
450
451  while ((pid = waitpid (-1, (int *)&status, WNOHANG)) > 0)
452    set_pid_status (pid, status);
453#endif
454}
455#endif /* WAITPID && WNOHANG */
456
457/* Fork, handling errors.  Returns the pid of the newly made child, or 0.
458   COMMAND is just for remembering the name of the command; we don't do
459   anything else with it.  ASYNC_P says what to do with the tty.  If
460   non-zero, then don't give it away. */
461pid_t
462make_child (command, async_p)
463     char *command;
464     int async_p;
465{
466  pid_t pid;
467#if defined (HAVE_WAITPID)
468  int retry = 1;
469#endif /* HAVE_WAITPID */
470
471  /* Discard saved memory. */
472  if (command)
473    free (command);
474
475  start_pipeline ();
476
477#if defined (BUFFERED_INPUT)
478  /* If default_buffered_input is active, we are reading a script.  If
479     the command is asynchronous, we have already duplicated /dev/null
480     as fd 0, but have not changed the buffered stream corresponding to
481     the old fd 0.  We don't want to sync the stream in this case. */
482  if (default_buffered_input != -1 && (!async_p || default_buffered_input > 0))
483    sync_buffered_stream (default_buffered_input);
484#endif /* BUFFERED_INPUT */
485
486  /* Create the child, handle severe errors. */
487#if defined (HAVE_WAITPID)
488  retry_fork:
489#endif /* HAVE_WAITPID */
490
491  if ((pid = fork ()) < 0)
492    {
493#if defined (HAVE_WAITPID)
494      /* Posix systems with a non-blocking waitpid () system call available
495         get another chance after zombies are reaped. */
496      if (errno == EAGAIN && retry)
497        {
498          reap_zombie_children ();
499          retry = 0;
500          goto retry_fork;
501        }
502#endif /* HAVE_WAITPID */
503
504      sys_error ("fork");
505
506      throw_to_top_level ();
507    }
508
509  if (pid == 0)
510    {
511#if defined (BUFFERED_INPUT)
512      unset_bash_input (0);
513#endif /* BUFFERED_INPUT */
514
515#if defined (HAVE_POSIX_SIGNALS)
516      /* Restore top-level signal mask. */
517      sigprocmask (SIG_SETMASK, &top_level_mask, (sigset_t *)NULL);
518#endif
519
520      /* Ignore INT and QUIT in asynchronous children. */
521      if (async_p)
522        last_asynchronous_pid = getpid ();
523
524      default_tty_job_signals ();
525    }
526  else
527    {
528      /* In the parent. */
529
530      last_made_pid = pid;
531
532      if (async_p)
533        last_asynchronous_pid = pid;
534
535      add_pid (pid, async_p);
536    }
537  return (pid);
538}
539
540void
541ignore_tty_job_signals ()
542{
543#if defined (SIGTSTP)
544  set_signal_handler (SIGTSTP, SIG_IGN);
545  set_signal_handler (SIGTTIN, SIG_IGN);
546  set_signal_handler (SIGTTOU, SIG_IGN);
547#endif
548}
549
550void
551default_tty_job_signals ()
552{
553#if defined (SIGTSTP)
554  set_signal_handler (SIGTSTP, SIG_DFL);
555  set_signal_handler (SIGTTIN, SIG_DFL);
556  set_signal_handler (SIGTTOU, SIG_DFL);
557#endif
558}
559
560/* Wait for a single pid (PID) and return its exit status.  Called by
561   the wait builtin. */
562int
563wait_for_single_pid (pid)
564     pid_t pid;
565{
566  pid_t got_pid;
567  WAIT status;
568  int pstatus;
569
570  pstatus = find_status_by_pid (pid);
571
572  if (pstatus == PROC_BAD)
573    {
574      internal_error ("wait: pid %ld is not a child of this shell", (long)pid);
575      return (127);
576    }
577
578  if (pstatus != PROC_STILL_ALIVE)
579    return (pstatus);
580
581  siginterrupt (SIGINT, 1);
582  while ((got_pid = WAITPID (pid, &status, 0)) != pid)
583    {
584      if (got_pid < 0)
585        {
586          if (errno != EINTR && errno != ECHILD)
587            {
588              siginterrupt (SIGINT, 0);
589              sys_error ("wait");
590            }
591          break;
592        }
593      else if (got_pid > 0)
594        set_pid_status (got_pid, status);
595    }
596
597  if (got_pid > 0)
598    {
599      set_pid_status (got_pid, status);
600      set_pid_flags (got_pid, PROC_NOTIFIED);
601    }
602
603  siginterrupt (SIGINT, 0);
604  QUIT;
605
606  return (got_pid > 0 ? process_exit_status (status) : -1);
607}
608
609/* Wait for all of the shell's children to exit.  Called by the `wait'
610   builtin. */
611void
612wait_for_background_pids ()
613{
614  pid_t got_pid;
615  WAIT status;
616
617  /* If we aren't using job control, we let the kernel take care of the
618     bookkeeping for us.  wait () will return -1 and set errno to ECHILD
619     when there are no more unwaited-for child processes on both
620     4.2 BSD-based and System V-based systems. */
621
622  siginterrupt (SIGINT, 1);
623
624  /* Wait for ECHILD */
625  while ((got_pid = WAITPID (-1, &status, 0)) != -1)
626    set_pid_status (got_pid, status);
627
628  if (errno != EINTR && errno != ECHILD)
629    {
630      siginterrupt (SIGINT, 0);
631      sys_error("wait");
632    }
633
634  siginterrupt (SIGINT, 0);
635  QUIT;
636
637  mark_dead_jobs_as_notified (1);
638  cleanup_dead_jobs ();
639}
640
641/* Make OLD_SIGINT_HANDLER the SIGINT signal handler. */
642#define INVALID_SIGNAL_HANDLER (SigHandler *)wait_for_background_pids
643static SigHandler *old_sigint_handler = INVALID_SIGNAL_HANDLER;
644
645static void
646restore_sigint_handler ()
647{
648  if (old_sigint_handler != INVALID_SIGNAL_HANDLER)
649    {
650      set_signal_handler (SIGINT, old_sigint_handler);
651      old_sigint_handler = INVALID_SIGNAL_HANDLER;
652    }
653}
654
655/* Handle SIGINT while we are waiting for children in a script to exit.
656   All interrupts are effectively ignored by the shell, but allowed to
657   kill a running job. */
658static sighandler
659wait_sigint_handler (sig)
660     int sig;
661{
662  SigHandler *sigint_handler;
663
664  /* If we got a SIGINT while in `wait', and SIGINT is trapped, do
665     what POSIX.2 says (see builtins/wait.def for more info). */
666  if (this_shell_builtin && this_shell_builtin == wait_builtin &&
667      signal_is_trapped (SIGINT) &&
668      ((sigint_handler = trap_to_sighandler (SIGINT)) == trap_handler))
669    {
670      last_command_exit_value = EXECUTION_FAILURE;
671      restore_sigint_handler ();
672      interrupt_immediately = 0;
673      trap_handler (SIGINT);    /* set pending_traps[SIGINT] */
674      wait_signal_received = SIGINT;
675      longjmp (wait_intr_buf, 1);
676    }
677
678  if (interrupt_immediately)
679    {
680      last_command_exit_value = EXECUTION_FAILURE;
681      restore_sigint_handler ();
682      ADDINTERRUPT;
683      QUIT;
684    }
685
686  wait_sigint_received = 1;
687
688  SIGRETURN (0);
689}
690
691/* Wait for pid (one of our children) to terminate.  This is called only
692   by the execution code in execute_cmd.c. */
693int
694wait_for (pid)
695     pid_t pid;
696{
697  int return_val, pstatus;
698  pid_t got_pid;
699  WAIT status;
700
701  pstatus = find_status_by_pid (pid);
702
703  if (pstatus == PROC_BAD)
704    return (0);
705
706  if (pstatus != PROC_STILL_ALIVE)
707    return (pstatus);
708
709  /* If we are running a script, ignore SIGINT while we're waiting for
710     a child to exit.  The loop below does some of this, but not all. */
711  wait_sigint_received = 0;
712  if (interactive_shell == 0)
713    old_sigint_handler = set_signal_handler (SIGINT, wait_sigint_handler);
714
715  while ((got_pid = WAITPID (-1, &status, 0)) != pid) /* XXX was pid now -1 */
716    {
717      if (got_pid < 0 && errno == ECHILD)
718        {
719#if !defined (_POSIX_VERSION)
720          status.w_termsig = status.w_retcode = 0;
721#else
722          status = 0;
723#endif /* _POSIX_VERSION */
724          break;
725        }
726      else if (got_pid < 0 && errno != EINTR)
727        programming_error ("wait_for(%ld): %s", (long)pid, strerror(errno));
728      else if (got_pid > 0)
729        set_pid_status (got_pid, status);
730    }
731
732  if (got_pid > 0)
733    set_pid_status (got_pid, status);
734
735#if defined (HAVE_WAITPID)
736  if (got_pid >= 0)
737    reap_zombie_children ();
738#endif /* HAVE_WAITPID */
739
740  if (interactive_shell == 0)
741    {
742      SigHandler *temp_handler;
743
744      temp_handler = old_sigint_handler;
745      restore_sigint_handler ();
746
747      /* If the job exited because of SIGINT, make sure the shell acts as if
748         it had received one also. */
749      if (WIFSIGNALED (status) && (WTERMSIG (status) == SIGINT))
750        {
751
752          if (maybe_call_trap_handler (SIGINT) == 0)
753            {
754              if (temp_handler == SIG_DFL)
755                termination_unwind_protect (SIGINT);
756              else if (temp_handler != INVALID_SIGNAL_HANDLER && temp_handler != SIG_IGN)
757                (*temp_handler) (SIGINT);
758            }
759        }
760    }
761
762  /* Default return value. */
763  /* ``a full 8 bits of status is returned'' */
764  return_val = process_exit_status (status);
765
766#if !defined (DONT_REPORT_SIGPIPE)
767  if ((WIFSTOPPED (status) == 0) && WIFSIGNALED (status) &&
768        (WTERMSIG (status) != SIGINT))
769#else
770  if ((WIFSTOPPED (status) == 0) && WIFSIGNALED (status) &&
771        (WTERMSIG (status) != SIGINT) && (WTERMSIG (status) != SIGPIPE))
772#endif
773    {
774      fprintf (stderr, "%s", strsignal (WTERMSIG (status)));
775      if (WIFCORED (status))
776        fprintf (stderr, " (core dumped)");
777      fprintf (stderr, "\n");
778    }
779
780  if (interactive_shell && subshell_environment == 0)
781    {
782      if (WIFSIGNALED (status) || WIFSTOPPED (status))
783        set_tty_state ();
784      else
785        get_tty_state ();
786    }
787
788  return (return_val);
789}
790
791/* Give PID SIGNAL.  This determines what job the pid belongs to (if any).
792   If PID does belong to a job, and the job is stopped, then CONTinue the
793   job after giving it SIGNAL.  Returns -1 on failure.  If GROUP is non-null,
794   then kill the process group associated with PID. */
795int
796kill_pid (pid, signal, group)
797     pid_t pid;
798     int signal, group;
799{
800  int result;
801
802  result = group ? killpg (pid, signal) : kill (pid, signal);
803  return (result);
804}
805
806static TTYSTRUCT shell_tty_info;
807static int got_tty_state;
808
809/* Fill the contents of shell_tty_info with the current tty info. */
810get_tty_state ()
811{
812  int tty;
813
814  tty = input_tty ();
815  if (tty != -1)
816    {
817      ttgetattr (tty, &shell_tty_info);
818      got_tty_state = 1;
819      if (check_window_size)
820        get_new_window_size (0);
821    }
822}
823
824/* Make the current tty use the state in shell_tty_info. */
825int
826set_tty_state ()
827{
828  int tty;
829
830  tty = input_tty ();
831  if (tty != -1)
832    {
833      if (got_tty_state == 0)
834        return 0;
835      ttsetattr (tty, &shell_tty_info);
836    }
837  return 0;
838}
839
840/* Give the terminal to PGRP.  */
841give_terminal_to (pgrp, force)
842     pid_t pgrp;
843     int force;
844{
845}
846
847/* Stop a pipeline. */
848int
849stop_pipeline (async, ignore)
850     int async;
851     COMMAND *ignore;
852{
853  already_making_children = 0;
854  return 0;
855}
856
857void
858start_pipeline ()
859{
860  already_making_children = 1;
861}
862
863void
864stop_making_children ()
865{
866  already_making_children = 0;
867}
868
869int
870get_job_by_pid (pid, block)
871     pid_t pid;
872     int block;
873{
874  int i;
875
876  i = find_index_by_pid (pid);
877  return ((i == NO_PID) ? PROC_BAD : i);
878}
879
880/* Print descriptive information about the job with leader pid PID. */
881void
882describe_pid (pid)
883     pid_t pid;
884{
885  fprintf (stderr, "%ld\n", (long) pid);
886}
887
888void
889unfreeze_jobs_list ()
890{
891}
892
893int
894count_all_jobs ()
895{
896  return 0;
897}
Note: See TracBrowser for help on using the repository browser.