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