diff options
Diffstat (limited to 'sys-utils/setsid.c')
-rw-r--r-- | sys-utils/setsid.c | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/sys-utils/setsid.c b/sys-utils/setsid.c new file mode 100644 index 0000000..071ccc4 --- /dev/null +++ b/sys-utils/setsid.c @@ -0,0 +1,98 @@ +/* + * setsid.c -- execute a command in a new session + * Rick Sladkey <jrs@world.std.com> + * In the public domain. + * + * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL> + * - added Native Language Support + * + * 2001-01-18 John Fremlin <vii@penguinpowered.com> + * - fork in case we are process group leader + * + */ + +#include <getopt.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/ioctl.h> + +#include "c.h" +#include "nls.h" +#include "closestream.h" + +static void __attribute__ ((__noreturn__)) usage(FILE * out) +{ + fputs(USAGE_HEADER, out); + fprintf(out, _( + " %s [options] <program> [arguments ...]\n"), + program_invocation_short_name); + + fputs(USAGE_OPTIONS, out); + fputs(_(" -c, --ctty set the controlling terminal to the current one\n"), + out); + + fputs(USAGE_HELP, out); + fputs(USAGE_VERSION, out); + + fprintf(out, USAGE_MAN_TAIL("setsid(1)")); + exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS); +} + +int main(int argc, char **argv) +{ + int ch; + int ctty = 0; + + static const struct option longopts[] = { + {"ctty", no_argument, NULL, 'c'}, + {"version", no_argument, NULL, 'V'}, + {"help", no_argument, NULL, 'h'}, + {NULL, 0, NULL, 0} + }; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + atexit(close_stdout); + + while ((ch = getopt_long(argc, argv, "+Vhc", longopts, NULL)) != -1) + switch (ch) { + case 'V': + printf(UTIL_LINUX_VERSION); + return EXIT_SUCCESS; + case 'c': + ctty=1; + break; + case 'h': + usage(stdout); + default: + usage(stderr); + } + + if (argc < 2) + usage(stderr); + + if (getpgrp() == getpid()) { + switch (fork()) { + case -1: + err(EXIT_FAILURE, _("fork")); + case 0: + /* child */ + break; + default: + /* parent */ + return 0; + } + } + if (setsid() < 0) + /* cannot happen */ + err(EXIT_FAILURE, _("setsid failed")); + + if (ctty) { + if (ioctl(STDIN_FILENO, TIOCSCTTY, 1)) + warn(_("failed to set the controlling terminal")); + } + execvp(argv[optind], argv + optind); + err(EXIT_FAILURE, _("execvp failed")); +} |