]> git.ipfire.org Git - thirdparty/util-linux.git/blame - sys-utils/setsid.c
script: add note about --log-in and passwords
[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
6e1eda6f 28static void __attribute__((__noreturn__)) usage(void)
cbfa3253 29{
6e1eda6f 30 FILE *out = stdout;
7c3c355f 31 fputs(USAGE_HEADER, out);
8a2f04dd 32 fprintf(out, _(
7c3c355f
KZ
33 " %s [options] <program> [arguments ...]\n"),
34 program_invocation_short_name);
35
451dbcfa
BS
36 fputs(USAGE_SEPARATOR, out);
37 fputs(_("Run a program in a new session.\n"), out);
38
7c3c355f 39 fputs(USAGE_OPTIONS, out);
0dde1997 40 fputs(_(" -c, --ctty set the controlling terminal to the current one\n"), out);
18017621 41 fputs(_(" -f, --fork always fork\n"), out);
0dde1997 42 fputs(_(" -w, --wait wait program to exit, and use the same return\n"), out);
7c3c355f 43
f45f3ec3 44 printf(USAGE_HELP_OPTIONS(16));
7c3c355f 45
f45f3ec3 46 printf(USAGE_MAN_TAIL("setsid(1)"));
6e1eda6f 47 exit(EXIT_SUCCESS);
cbfa3253
SK
48}
49
50int main(int argc, char **argv)
51{
18017621 52 int ch, forcefork = 0;
8a2f04dd 53 int ctty = 0;
0dde1997
DKG
54 pid_t pid;
55 int status = 0;
8a2f04dd 56
cbfa3253 57 static const struct option longopts[] = {
8a2f04dd 58 {"ctty", no_argument, NULL, 'c'},
18017621 59 {"fork", no_argument, NULL, 'f'},
0dde1997 60 {"wait", no_argument, NULL, 'w'},
cbfa3253
SK
61 {"version", no_argument, NULL, 'V'},
62 {"help", no_argument, NULL, 'h'},
63 {NULL, 0, NULL, 0}
64 };
65
7eda085c
KZ
66 setlocale(LC_ALL, "");
67 bindtextdomain(PACKAGE, LOCALEDIR);
68 textdomain(PACKAGE);
2c308875 69 close_stdout_atexit();
cbfa3253 70
18017621 71 while ((ch = getopt_long(argc, argv, "+Vhcfw", longopts, NULL)) != -1)
cbfa3253 72 switch (ch) {
8a2f04dd
HH
73 case 'c':
74 ctty=1;
75 break;
18017621
KZ
76 case 'f':
77 forcefork = 1;
78 break;
0dde1997
DKG
79 case 'w':
80 status = 1;
81 break;
2c308875 82
cbfa3253 83 case 'h':
6e1eda6f 84 usage();
2c308875
KZ
85 case 'V':
86 print_version(EXIT_SUCCESS);
cbfa3253 87 default:
677ec86c 88 errtryhelp(EXIT_FAILURE);
cbfa3253
SK
89 }
90
6e1eda6f
RM
91 if (argc - optind < 1) {
92 warnx(_("no command specified"));
93 errtryhelp(EXIT_FAILURE);
94 }
cbfa3253 95
18017621 96 if (forcefork || getpgrp() == getpid()) {
0dde1997
DKG
97 pid = fork();
98 switch (pid) {
c07ebfa1 99 case -1:
cbfa3253
SK
100 err(EXIT_FAILURE, _("fork"));
101 case 0:
102 /* child */
c07ebfa1 103 break;
cbfa3253
SK
104 default:
105 /* parent */
0dde1997
DKG
106 if (!status)
107 return EXIT_SUCCESS;
108 if (wait(&status) != pid)
109 err(EXIT_FAILURE, "wait");
110 if (WIFEXITED(status))
111 return WEXITSTATUS(status);
112 err(status, _("child %d did not exit normally"), pid);
c07ebfa1
KZ
113 }
114 }
cbfa3253
SK
115 if (setsid() < 0)
116 /* cannot happen */
117 err(EXIT_FAILURE, _("setsid failed"));
118
74ce680a
SK
119 if (ctty && ioctl(STDIN_FILENO, TIOCSCTTY, 1))
120 err(EXIT_FAILURE, _("failed to set the controlling terminal"));
b4479ffa 121 execvp(argv[optind], argv + optind);
fd777151 122 errexec(argv[optind]);
6dbe3af9 123}