summaryrefslogtreecommitdiff
path: root/builtins/suspend.def
blob: 8711e681733807a7452939927555e5ba3d5b9510 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
This file is suspend.def, from which is created suspend.c.
It implements the builtin "suspend" in Bash.

Copyright (C) 1987-2009 Free Software Foundation, Inc.

This file is part of GNU Bash, the Bourne Again SHell.

Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Bash.  If not, see <http://www.gnu.org/licenses/>.

$PRODUCES suspend.c

$BUILTIN suspend
$DEPENDS_ON JOB_CONTROL
$FUNCTION suspend_builtin
$SHORT_DOC suspend [-f]
Suspend shell execution.

Suspend the execution of this shell until it receives a SIGCONT signal.
Unless forced, login shells cannot be suspended.

Options:
  -f	force the suspend, even if the shell is a login shell

Exit Status:
Returns success unless job control is not enabled or an error occurs.
$END

#include <config.h>

#if defined (JOB_CONTROL)
#if defined (HAVE_UNISTD_H)
#  ifdef _MINIX
#    include <sys/types.h>
#  endif
#  include <unistd.h>
#endif

#include "../bashtypes.h"
#include <signal.h>
#include "../bashintl.h"
#include "../shell.h"
#include "../jobs.h"
#include "common.h"
#include "bashgetopt.h"

static sighandler suspend_continue __P((int));

static SigHandler *old_cont;
#if 0
static SigHandler *old_stop;
#endif

/* Continue handler. */
static sighandler
suspend_continue (sig)
     int sig;
{
  set_signal_handler (SIGCONT, old_cont);
#if 0
  set_signal_handler (SIGSTOP, old_stop);
#endif
  SIGRETURN (0);
}

/* Suspending the shell.  If -f is the arg, then do the suspend
   no matter what.  Otherwise, complain if a login shell. */
int
suspend_builtin (list)
     WORD_LIST *list;
{
  int opt, force;

  reset_internal_getopt ();
  force = 0;
  while ((opt = internal_getopt (list, "f")) != -1)
    switch (opt)
      {
      case 'f':
	force++;
	break;
      default:
	builtin_usage ();
	return (EX_USAGE);
      }
      
  list = loptend;

  if (job_control == 0)
    {
      sh_nojobs (_("cannot suspend"));
      return (EXECUTION_FAILURE);
    }

  if (force == 0)  
    {
      no_args (list);

      if (login_shell)
	{
	  builtin_error (_("cannot suspend a login shell"));
	  return (EXECUTION_FAILURE);
	}
    }

  /* XXX - should we put ourselves back into the original pgrp now?  If so,
     call end_job_control() here and do the right thing in suspend_continue
     (that is, call restart_job_control()). */
  old_cont = (SigHandler *)set_signal_handler (SIGCONT, suspend_continue);
#if 0
  old_stop = (SigHandler *)set_signal_handler (SIGSTOP, SIG_DFL);
#endif
  killpg (shell_pgrp, SIGSTOP);
  return (EXECUTION_SUCCESS);
}

#endif /* JOB_CONTROL */