2 * Copyright (c) 1980 Regents of the University of California.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * 1999-02-22 Arkadiusz MiĆkiewicz <misiek@pld.ORG.PL>
36 * - added Native Language Support
38 * 2000-07-30 Per Andreas Buer <per@linpro.no> - added "q"-option
40 * 2014-05-30 Csaba Kos <csaba.kos@gmail.com>
41 * - fixed a rare deadlock after child termination
50 #include <sys/ioctl.h>
63 #include <sys/signalfd.h>
67 #include "closestream.h"
72 #include "monotonic.h"
73 #include "timeutils.h"
78 static UL_DEBUG_DEFINE_MASK(script
);
79 UL_DEBUG_DEFINE_MASKNAMES(script
) = UL_DEBUG_EMPTY_MASKNAMES
;
81 #define SCRIPT_DEBUG_INIT (1 << 1)
82 #define SCRIPT_DEBUG_POLL (1 << 2)
83 #define SCRIPT_DEBUG_SIGNAL (1 << 3)
84 #define SCRIPT_DEBUG_IO (1 << 4)
85 #define SCRIPT_DEBUG_MISC (1 << 5)
86 #define SCRIPT_DEBUG_ALL 0xFFFF
88 #define DBG(m, x) __UL_DBG(script, SCRIPT_DEBUG_, m, x)
89 #define ON_DBG(m, x) __UL_DBG_CALL(script, SCRIPT_DEBUG_, m, x)
91 #if defined(HAVE_LIBUTIL) && defined(HAVE_PTY_H)
95 #ifdef HAVE_LIBUTEMPTER
96 # include <utempter.h>
99 #define DEFAULT_TYPESCRIPT_FILENAME "typescript"
101 struct script_control
{
102 char *shell
; /* shell to be executed */
103 char *command
; /* command to be executed */
104 char *fname
; /* output file path */
105 FILE *typescriptfp
; /* output file pointer */
106 char *tname
; /* timing file path */
107 FILE *timingfp
; /* timing file pointer */
108 uint64_t outsz
; /* current output file size */
109 uint64_t maxsz
; /* maximum output file size */
110 struct timeval oldtime
; /* previous write or command start time */
111 int master
; /* pseudoterminal master file descriptor */
112 int slave
; /* pseudoterminal slave file descriptor */
113 int poll_timeout
; /* poll() timeout, used in end of execution */
114 pid_t child
; /* child pid */
115 int childstatus
; /* child process exit value */
116 struct termios attrs
; /* slave terminal runtime attributes */
117 struct winsize win
; /* terminal window size */
118 #if !HAVE_LIBUTIL || !HAVE_PTY_H
119 char *line
; /* terminal line */
122 append
:1, /* append output */
123 rc_wanted
:1, /* return child exit value */
124 flush
:1, /* flush after each write */
125 quiet
:1, /* suppress most output */
126 timing
:1, /* include timing file */
127 force
:1, /* write output to links */
128 isterm
:1, /* is child process running as terminal */
129 die
:1; /* terminate program */
131 sigset_t sigset
; /* catch SIGCHLD and SIGWINCH with signalfd() */
132 sigset_t sigorg
; /* original signal mask */
133 int sigfd
; /* file descriptor for signalfd() */
136 static void script_init_debug(void)
138 __UL_INIT_DEBUG_FROM_ENV(script
, SCRIPT_DEBUG_
, 0, SCRIPT_DEBUG
);
142 * For tests we want to be able to control time output
145 static inline time_t script_time(time_t *t
)
147 const char *str
= getenv("SCRIPT_TEST_SECOND_SINCE_EPOCH");
150 if (!str
|| sscanf(str
, "%"SCNi64
, &sec
) != 1)
156 #else /* !TEST_SCRIPT */
157 # define script_time(x) time(x)
160 static void __attribute__((__noreturn__
)) usage(void)
163 fputs(USAGE_HEADER
, out
);
164 fprintf(out
, _(" %s [options] [file]\n"), program_invocation_short_name
);
166 fputs(USAGE_SEPARATOR
, out
);
167 fputs(_("Make a typescript of a terminal session.\n"), out
);
169 fputs(USAGE_OPTIONS
, out
);
170 fputs(_(" -a, --append append the output\n"
171 " -c, --command <command> run command rather than interactive shell\n"
172 " -e, --return return exit code of the child process\n"
173 " -f, --flush run flush after each write\n"
174 " --force use output file even when it is a link\n"
175 " -o, --output-limit <size> terminate if output files exceed size\n"
176 " -q, --quiet be quiet\n"
177 " -t[<file>], --timing[=<file>] output timing data to stderr or to FILE\n"
179 printf(USAGE_HELP_OPTIONS(31));
181 printf(USAGE_MAN_TAIL("script(1)"));
185 static void die_if_link(const struct script_control
*ctl
)
191 if (lstat(ctl
->fname
, &s
) == 0 && (S_ISLNK(s
.st_mode
) || s
.st_nlink
> 1))
193 _("output file `%s' is a link\n"
194 "Use --force if you really want to use it.\n"
195 "Program not started."), ctl
->fname
);
198 static void restore_tty(struct script_control
*ctl
, int mode
)
206 tcsetattr(STDIN_FILENO
, mode
, &rtt
);
209 static void enable_rawmode_tty(struct script_control
*ctl
)
218 rtt
.c_lflag
&= ~ECHO
;
219 tcsetattr(STDIN_FILENO
, TCSANOW
, &rtt
);
222 static void __attribute__((__noreturn__
)) done(struct script_control
*ctl
)
224 DBG(MISC
, ul_debug("done!"));
226 restore_tty(ctl
, TCSADRAIN
);
228 if (ctl
->typescriptfp
) {
229 char buf
[FORMAT_TIMESTAMP_MAX
];
230 time_t tvec
= script_time((time_t *)NULL
);
232 strtime_iso(&tvec
, ISO_TIMESTAMP
, buf
, sizeof(buf
));
233 fprintf(ctl
->typescriptfp
, _("\nScript done on %s\n"), buf
);
236 if (!ctl
->quiet
&& ctl
->typescriptfp
)
237 printf(_("Script done, file is %s\n"), ctl
->fname
);
238 #ifdef HAVE_LIBUTEMPTER
239 if (ctl
->master
>= 0)
240 utempter_remove_record(ctl
->master
);
242 kill(ctl
->child
, SIGTERM
); /* make sure we don't create orphans */
244 if (ctl
->timingfp
&& close_stream(ctl
->timingfp
) != 0)
245 err(EXIT_FAILURE
, "write failed: %s", ctl
->tname
);
246 if (ctl
->typescriptfp
&& close_stream(ctl
->typescriptfp
) != 0)
247 err(EXIT_FAILURE
, "write failed: %s", ctl
->fname
);
249 if (ctl
->rc_wanted
) {
250 if (WIFSIGNALED(ctl
->childstatus
))
251 exit(WTERMSIG(ctl
->childstatus
) + 0x80);
253 exit(WEXITSTATUS(ctl
->childstatus
));
258 static void __attribute__((__noreturn__
)) fail(struct script_control
*ctl
)
260 DBG(MISC
, ul_debug("fail!"));
265 static void wait_for_child(struct script_control
*ctl
, int wait
)
269 int options
= wait
? 0 : WNOHANG
;
271 DBG(MISC
, ul_debug("waiting for child"));
273 while ((pid
= wait3(&status
, options
, NULL
)) > 0)
274 if (pid
== ctl
->child
)
275 ctl
->childstatus
= status
;
278 static void write_output(struct script_control
*ctl
, char *obuf
,
281 int timing_bytes
= 0;
283 DBG(IO
, ul_debug(" writing output"));
285 if (ctl
->timing
&& ctl
->timingfp
) {
286 struct timeval now
, delta
;
288 DBG(IO
, ul_debug(" writing timing info"));
290 gettime_monotonic(&now
);
291 timersub(&now
, &ctl
->oldtime
, &delta
);
292 timing_bytes
= fprintf(ctl
->timingfp
, "%ld.%06ld %zd\n",
293 (long)delta
.tv_sec
, (long)delta
.tv_usec
, bytes
);
295 fflush(ctl
->timingfp
);
297 if (timing_bytes
< 0)
301 DBG(IO
, ul_debug(" writing to script file"));
303 if (fwrite_all(obuf
, 1, bytes
, ctl
->typescriptfp
)) {
304 warn(_("cannot write script file"));
308 fflush(ctl
->typescriptfp
);
310 DBG(IO
, ul_debug(" writing to output"));
312 if (write_all(STDOUT_FILENO
, obuf
, bytes
)) {
313 DBG(IO
, ul_debug(" writing output *failed*"));
314 warn(_("write failed"));
319 ctl
->outsz
+= bytes
+ timing_bytes
;
321 DBG(IO
, ul_debug(" writing output *done*"));
324 static int write_to_shell(struct script_control
*ctl
,
325 char *buf
, size_t bufsz
)
327 return write_all(ctl
->master
, buf
, bufsz
);
331 * The script(1) is usually faster than shell, so it's a good idea to wait until
332 * the previous message has been already read by shell from slave before we
333 * write to master. This is necessary especially for EOF situation when we can
334 * send EOF to master before shell is fully initialized, to workaround this
335 * problem we wait until slave is empty. For example:
337 * echo "date" | script
339 * Unfortunately, the child (usually shell) can ignore stdin at all, so we
340 * don't wait forever to avoid dead locks...
342 * Note that script is primarily designed for interactive sessions as it
343 * maintains master+slave tty stuff within the session. Use pipe to write to
344 * script(1) and assume non-interactive (tee-like) behavior is NOT well
347 static void write_eof_to_shell(struct script_control
*ctl
)
349 unsigned int tries
= 0;
350 struct pollfd fds
[] = {
351 { .fd
= ctl
->slave
, .events
= POLLIN
}
355 DBG(IO
, ul_debug(" waiting for empty slave"));
356 while (poll(fds
, 1, 10) == 1 && tries
< 8) {
357 DBG(IO
, ul_debug(" slave is not empty"));
362 DBG(IO
, ul_debug(" slave is empty now"));
364 DBG(IO
, ul_debug(" sending EOF to master"));
365 write_to_shell(ctl
, &c
, sizeof(char));
368 static void handle_io(struct script_control
*ctl
, int fd
, int *eof
)
372 DBG(IO
, ul_debug("%d FD active", fd
));
375 /* read from active FD */
376 bytes
= read(fd
, buf
, sizeof(buf
));
378 if (errno
== EAGAIN
|| errno
== EINTR
)
388 /* from stdin (user) to command */
389 if (fd
== STDIN_FILENO
) {
390 DBG(IO
, ul_debug(" stdin --> master %zd bytes", bytes
));
392 if (write_to_shell(ctl
, buf
, bytes
)) {
393 warn(_("write failed"));
396 /* without sync write_output() will write both input &
397 * shell output that looks like double echoing */
398 fdatasync(ctl
->master
);
400 /* from command (master) to stdout and log */
401 } else if (fd
== ctl
->master
) {
402 DBG(IO
, ul_debug(" master --> stdout %zd bytes", bytes
));
403 write_output(ctl
, buf
, bytes
);
405 /* check output limit */
406 if (ctl
->maxsz
!= 0 && ctl
->outsz
>= ctl
->maxsz
) {
408 printf(_("Script terminated, max output file size %zd exceeded.\n"), ctl
->maxsz
);
409 DBG(IO
, ul_debug("output size %zd, exceeded limit %zd", ctl
->outsz
, ctl
->maxsz
));
415 static void handle_signal(struct script_control
*ctl
, int fd
)
417 struct signalfd_siginfo info
;
420 DBG(SIGNAL
, ul_debug("signal FD %d active", fd
));
422 bytes
= read(fd
, &info
, sizeof(info
));
423 if (bytes
!= sizeof(info
)) {
424 if (bytes
< 0 && (errno
== EAGAIN
|| errno
== EINTR
))
429 switch (info
.ssi_signo
) {
431 DBG(SIGNAL
, ul_debug(" get signal SIGCHLD"));
432 if (info
.ssi_code
== CLD_EXITED
) {
433 wait_for_child(ctl
, 0);
434 ctl
->poll_timeout
= 10;
435 } else if (info
.ssi_status
== SIGSTOP
&& ctl
->child
) {
436 DBG(SIGNAL
, ul_debug(" child stop by SIGSTOP -- stop parent too"));
437 kill(getpid(), SIGSTOP
);
438 DBG(SIGNAL
, ul_debug(" resume"));
439 kill(ctl
->child
, SIGCONT
);
443 DBG(SIGNAL
, ul_debug(" get signal SIGWINCH"));
445 ioctl(STDIN_FILENO
, TIOCGWINSZ
, (char *)&ctl
->win
);
446 ioctl(ctl
->slave
, TIOCSWINSZ
, (char *)&ctl
->win
);
454 DBG(SIGNAL
, ul_debug(" get signal SIG{TERM,INT,QUIT}"));
455 fprintf(stderr
, _("\nSession terminated.\n"));
456 /* Child termination is going to generate SIGCHILD (see above) */
457 kill(ctl
->child
, SIGTERM
);
464 static void do_io(struct script_control
*ctl
)
467 time_t tvec
= script_time((time_t *)NULL
);
474 struct pollfd pfd
[] = {
475 [POLLFD_SIGNAL
] = { .fd
= ctl
->sigfd
, .events
= POLLIN
| POLLERR
| POLLHUP
},
476 [POLLFD_MASTER
] = { .fd
= ctl
->master
, .events
= POLLIN
| POLLERR
| POLLHUP
},
477 [POLLFD_STDIN
] = { .fd
= STDIN_FILENO
, .events
= POLLIN
| POLLERR
| POLLHUP
}
481 if ((ctl
->typescriptfp
=
482 fopen(ctl
->fname
, ctl
->append
? "a" UL_CLOEXECSTR
: "w" UL_CLOEXECSTR
)) == NULL
) {
484 restore_tty(ctl
, TCSANOW
);
485 warn(_("cannot open %s"), ctl
->fname
);
489 const char *tname
= ctl
->tname
? ctl
->tname
: "/dev/stderr";
491 if (!(ctl
->timingfp
= fopen(tname
, "w" UL_CLOEXECSTR
))) {
492 restore_tty(ctl
, TCSANOW
);
493 warn(_("cannot open %s"), tname
);
499 if (ctl
->typescriptfp
) {
500 char buf
[FORMAT_TIMESTAMP_MAX
];
501 strtime_iso(&tvec
, ISO_TIMESTAMP
, buf
, sizeof(buf
));
502 fprintf(ctl
->typescriptfp
, _("Script started on %s\n"), buf
);
504 gettime_monotonic(&ctl
->oldtime
);
510 DBG(POLL
, ul_debug("calling poll()"));
512 /* wait for input or signal */
513 ret
= poll(pfd
, ARRAY_SIZE(pfd
), ctl
->poll_timeout
);
515 DBG(POLL
, ul_debug("poll() rc=%d", ret
));
520 warn(_("poll failed"));
524 DBG(POLL
, ul_debug("setting die=1"));
529 for (i
= 0; i
< ARRAY_SIZE(pfd
); i
++) {
530 if (pfd
[i
].revents
== 0)
533 DBG(POLL
, ul_debug(" active pfd[%s].fd=%d %s %s %s",
534 i
== POLLFD_STDIN
? "stdin" :
535 i
== POLLFD_MASTER
? "master" :
536 i
== POLLFD_SIGNAL
? "signal" : "???",
538 pfd
[i
].revents
& POLLIN
? "POLLIN" : "",
539 pfd
[i
].revents
& POLLHUP
? "POLLHUP" : "",
540 pfd
[i
].revents
& POLLERR
? "POLLERR" : ""));
545 if (pfd
[i
].revents
& POLLIN
)
546 handle_io(ctl
, pfd
[i
].fd
, &eof
);
547 /* EOF maybe detected by two ways:
548 * A) poll() return POLLHUP event after close()
549 * B) read() returns 0 (no data) */
550 if ((pfd
[i
].revents
& POLLHUP
) || eof
) {
551 DBG(POLL
, ul_debug(" ignore FD"));
553 if (i
== POLLFD_STDIN
) {
554 write_eof_to_shell(ctl
);
555 DBG(POLL
, ul_debug(" ignore STDIN"));
560 handle_signal(ctl
, pfd
[i
].fd
);
566 DBG(POLL
, ul_debug("poll() done"));
569 wait_for_child(ctl
, 1);
574 static void getslave(struct script_control
*ctl
)
577 ctl
->line
[strlen("/dev/")] = 't';
578 ctl
->slave
= open(ctl
->line
, O_RDWR
| O_CLOEXEC
);
579 if (ctl
->slave
< 0) {
580 warn(_("cannot open %s"), ctl
->line
);
584 tcsetattr(ctl
->slave
, TCSANOW
, &ctl
->attrs
);
585 ioctl(ctl
->slave
, TIOCSWINSZ
, (char *)&ctl
->win
);
589 ioctl(ctl
->slave
, TIOCSCTTY
, 0);
592 /* don't use DBG() stuff here otherwise it will be in the typescript file */
593 static void __attribute__((__noreturn__
)) do_shell(struct script_control
*ctl
)
599 /* close things irrelevant for this process */
603 dup2(ctl
->slave
, STDIN_FILENO
);
604 dup2(ctl
->slave
, STDOUT_FILENO
);
605 dup2(ctl
->slave
, STDERR_FILENO
);
610 shname
= strrchr(ctl
->shell
, '/');
616 sigprocmask(SIG_SETMASK
, &ctl
->sigorg
, NULL
);
619 * When invoked from within /etc/csh.login, script spawns a csh shell
620 * that spawns programs that cannot be killed with a SIGTERM. This is
621 * because csh has a documented behavior wherein it disables all
622 * signals when processing the /etc/csh.* files.
624 * Let's restore the default behavior.
626 signal(SIGTERM
, SIG_DFL
);
628 if (access(ctl
->shell
, X_OK
) == 0) {
630 execl(ctl
->shell
, shname
, "-c", ctl
->command
, NULL
);
632 execl(ctl
->shell
, shname
, "-i", NULL
);
635 execlp(shname
, "-c", ctl
->command
, NULL
);
637 execlp(shname
, "-i", NULL
);
639 warn(_("failed to execute %s"), ctl
->shell
);
644 static void getmaster(struct script_control
*ctl
)
646 #if defined(HAVE_LIBUTIL) && defined(HAVE_PTY_H)
649 ctl
->isterm
= isatty(STDIN_FILENO
);
652 if (tcgetattr(STDIN_FILENO
, &ctl
->attrs
) != 0)
653 err(EXIT_FAILURE
, _("failed to get terminal attributes"));
654 ioctl(STDIN_FILENO
, TIOCGWINSZ
, (char *)&ctl
->win
);
655 rc
= openpty(&ctl
->master
, &ctl
->slave
, NULL
, &ctl
->attrs
, &ctl
->win
);
657 rc
= openpty(&ctl
->master
, &ctl
->slave
, NULL
, NULL
, NULL
);
660 warn(_("openpty failed"));
664 char *pty
, *bank
, *cp
;
666 ctl
->isterm
= isatty(STDIN_FILENO
);
668 pty
= &ctl
->line
[strlen("/dev/ptyp")];
669 for (bank
= "pqrs"; *bank
; bank
++) {
670 ctl
->line
[strlen("/dev/pty")] = *bank
;
672 if (access(ctl
->line
, F_OK
) != 0)
674 for (cp
= "0123456789abcdef"; *cp
; cp
++) {
676 ctl
->master
= open(ctl
->line
, O_RDWR
| O_CLOEXEC
);
677 if (ctl
->master
>= 0) {
678 char *tp
= &ctl
->line
[strlen("/dev/")];
681 /* verify slave side is usable */
683 ok
= access(ctl
->line
, R_OK
| W_OK
) == 0;
687 tcgetattr(STDIN_FILENO
, &ctl
->attrs
);
688 ioctl(STDIN_FILENO
, TIOCGWINSZ
, (char *)&ctl
->win
);
698 warn(_("out of pty's"));
700 #endif /* not HAVE_LIBUTIL */
702 DBG(IO
, ul_debug("master fd: %d", ctl
->master
));
705 int main(int argc
, char **argv
)
707 struct script_control ctl
= {
708 #if !HAVE_LIBUTIL || !HAVE_PTY_H
709 .line
= "/dev/ptyXX",
716 enum { FORCE_OPTION
= CHAR_MAX
+ 1 };
718 static const struct option longopts
[] = {
719 {"append", no_argument
, NULL
, 'a'},
720 {"command", required_argument
, NULL
, 'c'},
721 {"return", no_argument
, NULL
, 'e'},
722 {"flush", no_argument
, NULL
, 'f'},
723 {"force", no_argument
, NULL
, FORCE_OPTION
,},
724 {"output-limit", required_argument
, NULL
, 'o'},
725 {"quiet", no_argument
, NULL
, 'q'},
726 {"timing", optional_argument
, NULL
, 't'},
727 {"version", no_argument
, NULL
, 'V'},
728 {"help", no_argument
, NULL
, 'h'},
732 setlocale(LC_ALL
, "");
734 * script -t prints time delays as floating point numbers. The example
735 * program (scriptreplay) that we provide to handle this timing output
736 * is a perl script, and does not handle numbers in locale format (not
737 * even when "use locale;" is added). So, since these numbers are not
738 * for human consumption, it seems easiest to set LC_NUMERIC here.
740 setlocale(LC_NUMERIC
, "C");
741 bindtextdomain(PACKAGE
, LOCALEDIR
);
743 atexit(close_stdout
);
747 while ((ch
= getopt_long(argc
, argv
, "ac:efo:qt::Vh", longopts
, NULL
)) != -1)
753 ctl
.command
= optarg
;
765 ctl
.maxsz
= strtosize_or_err(optarg
, _("failed to parse output limit size"));
776 printf(UTIL_LINUX_VERSION
);
783 errtryhelp(EXIT_FAILURE
);
791 ctl
.fname
= DEFAULT_TYPESCRIPT_FILENAME
;
795 ctl
.shell
= getenv("SHELL");
796 if (ctl
.shell
== NULL
)
797 ctl
.shell
= _PATH_BSHELL
;
801 printf(_("Script started, file is %s\n"), ctl
.fname
);
802 enable_rawmode_tty(&ctl
);
804 #ifdef HAVE_LIBUTEMPTER
805 utempter_add_record(ctl
.master
, NULL
);
807 /* setup signal handler */
808 sigemptyset(&ctl
.sigset
);
809 sigaddset(&ctl
.sigset
, SIGCHLD
);
810 sigaddset(&ctl
.sigset
, SIGWINCH
);
811 sigaddset(&ctl
.sigset
, SIGTERM
);
812 sigaddset(&ctl
.sigset
, SIGINT
);
813 sigaddset(&ctl
.sigset
, SIGQUIT
);
815 /* block signals used for signalfd() to prevent the signals being
816 * handled according to their default dispositions */
817 sigprocmask(SIG_BLOCK
, &ctl
.sigset
, &ctl
.sigorg
);
819 if ((ctl
.sigfd
= signalfd(-1, &ctl
.sigset
, SFD_CLOEXEC
)) < 0)
820 err(EXIT_FAILURE
, _("cannot set signal handler"));
822 DBG(SIGNAL
, ul_debug("signal fd=%d", ctl
.sigfd
));
829 warn(_("fork failed"));
835 default: /* parent */
840 /* should not happen, all used functions are non-return */