2 * No copyright is claimed. This code is in the public domain; do with
5 * Written by Rick Sladkey <jrs@world.std.com>
7 * setsid.c -- execute a command in a new session
9 * 1999-02-22 Arkadiusz MiĆkiewicz <misiek@pld.ORG.PL>
10 * - added Native Language Support
12 * 2001-01-18 John Fremlin <vii@penguinpowered.com>
13 * - fork in case we are process group leader
15 * 2008-08-20 Daniel Kahn Gillmor <dkg@fifthhorseman.net>
16 * - if forked, wait on child process and emit its return code.
22 #include <sys/ioctl.h>
23 #include <sys/types.h>
28 #include "closestream.h"
30 static void __attribute__((__noreturn__
)) usage(void)
33 fputs(USAGE_HEADER
, out
);
35 " %s [options] <program> [arguments ...]\n"),
36 program_invocation_short_name
);
38 fputs(USAGE_SEPARATOR
, out
);
39 fputs(_("Run a program in a new session.\n"), out
);
41 fputs(USAGE_OPTIONS
, out
);
42 fputs(_(" -c, --ctty set the controlling terminal to the current one\n"), out
);
43 fputs(_(" -f, --fork always fork\n"), out
);
44 fputs(_(" -w, --wait wait program to exit, and use the same return\n"), out
);
46 fprintf(out
, USAGE_HELP_OPTIONS(16));
48 fprintf(out
, USAGE_MAN_TAIL("setsid(1)"));
52 int main(int argc
, char **argv
)
54 int ch
, forcefork
= 0;
59 static const struct option longopts
[] = {
60 {"ctty", no_argument
, NULL
, 'c'},
61 {"fork", no_argument
, NULL
, 'f'},
62 {"wait", no_argument
, NULL
, 'w'},
63 {"version", no_argument
, NULL
, 'V'},
64 {"help", no_argument
, NULL
, 'h'},
68 setlocale(LC_ALL
, "");
69 bindtextdomain(PACKAGE
, LOCALEDIR
);
71 close_stdout_atexit();
73 while ((ch
= getopt_long(argc
, argv
, "+Vhcfw", longopts
, NULL
)) != -1)
88 print_version(EXIT_SUCCESS
);
90 errtryhelp(EXIT_FAILURE
);
93 if (argc
- optind
< 1) {
94 warnx(_("no command specified"));
95 errtryhelp(EXIT_FAILURE
);
98 if (forcefork
|| getpgrp() == getpid()) {
102 err(EXIT_FAILURE
, _("fork"));
110 if (wait(&status
) != pid
)
111 err(EXIT_FAILURE
, "wait");
112 if (WIFEXITED(status
))
113 return WEXITSTATUS(status
);
114 err(status
, _("child %d did not exit normally"), pid
);
119 err(EXIT_FAILURE
, _("setsid failed"));
121 if (ctty
&& ioctl(STDIN_FILENO
, TIOCSCTTY
, 1))
122 err(EXIT_FAILURE
, _("failed to set the controlling terminal"));
123 execvp(argv
[optind
], argv
+ optind
);
124 errexec(argv
[optind
]);