]> git.ipfire.org Git - thirdparty/util-linux.git/blame - sys-utils/setsid.c
sys-utils: cleanup license lines, add SPDX
[thirdparty/util-linux.git] / sys-utils / setsid.c
CommitLineData
6dbe3af9 1/*
9abd5e4b
KZ
2 * No copyright is claimed. This code is in the public domain; do with
3 * it what you wish.
4 *
5 * Written by Rick Sladkey <jrs@world.std.com>
6 *
6dbe3af9 7 * setsid.c -- execute a command in a new session
7eda085c 8 *
b50945d4 9 * 1999-02-22 Arkadiusz Miƛkiewicz <misiek@pld.ORG.PL>
7eda085c
KZ
10 * - added Native Language Support
11 *
c07ebfa1
KZ
12 * 2001-01-18 John Fremlin <vii@penguinpowered.com>
13 * - fork in case we are process group leader
14 *
0dde1997
DKG
15 * 2008-08-20 Daniel Kahn Gillmor <dkg@fifthhorseman.net>
16 * - if forked, wait on child process and emit its return code.
6dbe3af9 17 */
cbfa3253 18#include <getopt.h>
6dbe3af9 19#include <stdio.h>
6dbe3af9 20#include <stdlib.h>
cbfa3253 21#include <unistd.h>
97669624 22#include <sys/ioctl.h>
0dde1997
DKG
23#include <sys/types.h>
24#include <sys/wait.h>
cbfa3253
SK
25
26#include "c.h"
7eda085c 27#include "nls.h"
efb8854f 28#include "closestream.h"
6dbe3af9 29
6e1eda6f 30static void __attribute__((__noreturn__)) usage(void)
cbfa3253 31{
6e1eda6f 32 FILE *out = stdout;
7c3c355f 33 fputs(USAGE_HEADER, out);
8a2f04dd 34 fprintf(out, _(
7c3c355f
KZ
35 " %s [options] <program> [arguments ...]\n"),
36 program_invocation_short_name);
37
451dbcfa
BS
38 fputs(USAGE_SEPARATOR, out);
39 fputs(_("Run a program in a new session.\n"), out);
40
7c3c355f 41 fputs(USAGE_OPTIONS, out);
0dde1997 42 fputs(_(" -c, --ctty set the controlling terminal to the current one\n"), out);
18017621 43 fputs(_(" -f, --fork always fork\n"), out);
0dde1997 44 fputs(_(" -w, --wait wait program to exit, and use the same return\n"), out);
7c3c355f 45
bad4c729 46 fprintf(out, USAGE_HELP_OPTIONS(16));
7c3c355f 47
bad4c729 48 fprintf(out, USAGE_MAN_TAIL("setsid(1)"));
6e1eda6f 49 exit(EXIT_SUCCESS);
cbfa3253
SK
50}
51
52int main(int argc, char **argv)
53{
18017621 54 int ch, forcefork = 0;
8a2f04dd 55 int ctty = 0;
0dde1997
DKG
56 pid_t pid;
57 int status = 0;
8a2f04dd 58
cbfa3253 59 static const struct option longopts[] = {
8a2f04dd 60 {"ctty", no_argument, NULL, 'c'},
18017621 61 {"fork", no_argument, NULL, 'f'},
0dde1997 62 {"wait", no_argument, NULL, 'w'},
cbfa3253
SK
63 {"version", no_argument, NULL, 'V'},
64 {"help", no_argument, NULL, 'h'},
65 {NULL, 0, NULL, 0}
66 };
67
7eda085c
KZ
68 setlocale(LC_ALL, "");
69 bindtextdomain(PACKAGE, LOCALEDIR);
70 textdomain(PACKAGE);
2c308875 71 close_stdout_atexit();
cbfa3253 72
18017621 73 while ((ch = getopt_long(argc, argv, "+Vhcfw", longopts, NULL)) != -1)
cbfa3253 74 switch (ch) {
8a2f04dd
HH
75 case 'c':
76 ctty=1;
77 break;
18017621
KZ
78 case 'f':
79 forcefork = 1;
80 break;
0dde1997
DKG
81 case 'w':
82 status = 1;
83 break;
2c308875 84
cbfa3253 85 case 'h':
6e1eda6f 86 usage();
2c308875
KZ
87 case 'V':
88 print_version(EXIT_SUCCESS);
cbfa3253 89 default:
677ec86c 90 errtryhelp(EXIT_FAILURE);
cbfa3253
SK
91 }
92
6e1eda6f
RM
93 if (argc - optind < 1) {
94 warnx(_("no command specified"));
95 errtryhelp(EXIT_FAILURE);
96 }
cbfa3253 97
18017621 98 if (forcefork || getpgrp() == getpid()) {
0dde1997
DKG
99 pid = fork();
100 switch (pid) {
c07ebfa1 101 case -1:
cbfa3253
SK
102 err(EXIT_FAILURE, _("fork"));
103 case 0:
104 /* child */
c07ebfa1 105 break;
cbfa3253
SK
106 default:
107 /* parent */
0dde1997
DKG
108 if (!status)
109 return EXIT_SUCCESS;
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);
c07ebfa1
KZ
115 }
116 }
cbfa3253
SK
117 if (setsid() < 0)
118 /* cannot happen */
119 err(EXIT_FAILURE, _("setsid failed"));
120
74ce680a
SK
121 if (ctty && ioctl(STDIN_FILENO, TIOCSCTTY, 1))
122 err(EXIT_FAILURE, _("failed to set the controlling terminal"));
b4479ffa 123 execvp(argv[optind], argv + optind);
fd777151 124 errexec(argv[optind]);
6dbe3af9 125}