]> git.ipfire.org Git - thirdparty/util-linux.git/blame - sys-utils/setsid.c
misc: simplify if clauses [oclint]
[thirdparty/util-linux.git] / sys-utils / setsid.c
CommitLineData
6dbe3af9
KZ
1/*
2 * setsid.c -- execute a command in a new session
3 * Rick Sladkey <jrs@world.std.com>
4 * In the public domain.
7eda085c 5 *
b50945d4 6 * 1999-02-22 Arkadiusz Miƛkiewicz <misiek@pld.ORG.PL>
7eda085c
KZ
7 * - added Native Language Support
8 *
c07ebfa1
KZ
9 * 2001-01-18 John Fremlin <vii@penguinpowered.com>
10 * - fork in case we are process group leader
11 *
0dde1997
DKG
12 * 2008-08-20 Daniel Kahn Gillmor <dkg@fifthhorseman.net>
13 * - if forked, wait on child process and emit its return code.
6dbe3af9
KZ
14 */
15
cbfa3253 16#include <getopt.h>
6dbe3af9 17#include <stdio.h>
6dbe3af9 18#include <stdlib.h>
cbfa3253 19#include <unistd.h>
97669624 20#include <sys/ioctl.h>
0dde1997
DKG
21#include <sys/types.h>
22#include <sys/wait.h>
cbfa3253
SK
23
24#include "c.h"
7eda085c 25#include "nls.h"
efb8854f 26#include "closestream.h"
6dbe3af9 27
cbfa3253
SK
28static void __attribute__ ((__noreturn__)) usage(FILE * out)
29{
7c3c355f 30 fputs(USAGE_HEADER, out);
8a2f04dd 31 fprintf(out, _(
7c3c355f
KZ
32 " %s [options] <program> [arguments ...]\n"),
33 program_invocation_short_name);
34
451dbcfa
BS
35 fputs(USAGE_SEPARATOR, out);
36 fputs(_("Run a program in a new session.\n"), out);
37
7c3c355f 38 fputs(USAGE_OPTIONS, out);
0dde1997
DKG
39 fputs(_(" -c, --ctty set the controlling terminal to the current one\n"), out);
40 fputs(_(" -w, --wait wait program to exit, and use the same return\n"), out);
7c3c355f
KZ
41
42 fputs(USAGE_HELP, out);
43 fputs(USAGE_VERSION, out);
44
cbfa3253
SK
45 fprintf(out, USAGE_MAN_TAIL("setsid(1)"));
46 exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
47}
48
49int main(int argc, char **argv)
50{
51 int ch;
8a2f04dd 52 int ctty = 0;
0dde1997
DKG
53 pid_t pid;
54 int status = 0;
8a2f04dd 55
cbfa3253 56 static const struct option longopts[] = {
8a2f04dd 57 {"ctty", no_argument, NULL, 'c'},
0dde1997 58 {"wait", no_argument, NULL, 'w'},
cbfa3253
SK
59 {"version", no_argument, NULL, 'V'},
60 {"help", no_argument, NULL, 'h'},
61 {NULL, 0, NULL, 0}
62 };
63
7eda085c
KZ
64 setlocale(LC_ALL, "");
65 bindtextdomain(PACKAGE, LOCALEDIR);
66 textdomain(PACKAGE);
efb8854f 67 atexit(close_stdout);
cbfa3253 68
0dde1997 69 while ((ch = getopt_long(argc, argv, "+Vhcw", longopts, NULL)) != -1)
cbfa3253
SK
70 switch (ch) {
71 case 'V':
72 printf(UTIL_LINUX_VERSION);
73 return EXIT_SUCCESS;
8a2f04dd
HH
74 case 'c':
75 ctty=1;
76 break;
0dde1997
DKG
77 case 'w':
78 status = 1;
79 break;
cbfa3253
SK
80 case 'h':
81 usage(stdout);
82 default:
83 usage(stderr);
84 }
85
aeb9298d 86 if (argc - optind < 1)
cbfa3253
SK
87 usage(stderr);
88
c07ebfa1 89 if (getpgrp() == getpid()) {
0dde1997
DKG
90 pid = fork();
91 switch (pid) {
c07ebfa1 92 case -1:
cbfa3253
SK
93 err(EXIT_FAILURE, _("fork"));
94 case 0:
95 /* child */
c07ebfa1 96 break;
cbfa3253
SK
97 default:
98 /* parent */
0dde1997
DKG
99 if (!status)
100 return EXIT_SUCCESS;
101 if (wait(&status) != pid)
102 err(EXIT_FAILURE, "wait");
103 if (WIFEXITED(status))
104 return WEXITSTATUS(status);
105 err(status, _("child %d did not exit normally"), pid);
c07ebfa1
KZ
106 }
107 }
cbfa3253
SK
108 if (setsid() < 0)
109 /* cannot happen */
110 err(EXIT_FAILURE, _("setsid failed"));
111
74ce680a
SK
112 if (ctty && ioctl(STDIN_FILENO, TIOCSCTTY, 1))
113 err(EXIT_FAILURE, _("failed to set the controlling terminal"));
b4479ffa 114 execvp(argv[optind], argv + optind);
07ff972e 115 err(EXIT_FAILURE, _("failed to execute %s"), argv[optind]);
6dbe3af9 116}