]> git.ipfire.org Git - thirdparty/util-linux.git/blob - sys-utils/setsid.c
setsid: fix off-by-one error in execvp call
[thirdparty/util-linux.git] / sys-utils / setsid.c
1 /*
2 * setsid.c -- execute a command in a new session
3 * Rick Sladkey <jrs@world.std.com>
4 * In the public domain.
5 *
6 * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
7 * - added Native Language Support
8 *
9 * 2001-01-18 John Fremlin <vii@penguinpowered.com>
10 * - fork in case we are process group leader
11 *
12 */
13
14 #include <getopt.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <unistd.h>
18 #include <sys/ioctl.h>
19
20 #include "c.h"
21 #include "nls.h"
22 #include "closestream.h"
23
24 static void __attribute__ ((__noreturn__)) usage(FILE * out)
25 {
26 fputs(USAGE_HEADER, out);
27 fprintf(out, _(
28 " %s [options] <program> [arguments ...]\n"),
29 program_invocation_short_name);
30
31 fputs(USAGE_OPTIONS, out);
32 fputs(_(" -c, --ctty set the controlling terminal to the current one\n"),
33 out);
34
35 fputs(USAGE_HELP, out);
36 fputs(USAGE_VERSION, out);
37
38 fprintf(out, USAGE_MAN_TAIL("setsid(1)"));
39 exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
40 }
41
42 int main(int argc, char **argv)
43 {
44 int ch;
45 int ctty = 0;
46
47 static const struct option longopts[] = {
48 {"ctty", no_argument, NULL, 'c'},
49 {"version", no_argument, NULL, 'V'},
50 {"help", no_argument, NULL, 'h'},
51 {NULL, 0, NULL, 0}
52 };
53
54 setlocale(LC_ALL, "");
55 bindtextdomain(PACKAGE, LOCALEDIR);
56 textdomain(PACKAGE);
57 atexit(close_stdout);
58
59 while ((ch = getopt_long(argc, argv, "+Vhc", longopts, NULL)) != -1)
60 switch (ch) {
61 case 'V':
62 printf(UTIL_LINUX_VERSION);
63 return EXIT_SUCCESS;
64 case 'c':
65 ctty=1;
66 break;
67 case 'h':
68 usage(stdout);
69 default:
70 usage(stderr);
71 }
72
73 if (argc < 2)
74 usage(stderr);
75
76 if (getpgrp() == getpid()) {
77 switch (fork()) {
78 case -1:
79 err(EXIT_FAILURE, _("fork"));
80 case 0:
81 /* child */
82 break;
83 default:
84 /* parent */
85 return 0;
86 }
87 }
88 if (setsid() < 0)
89 /* cannot happen */
90 err(EXIT_FAILURE, _("setsid failed"));
91
92 if (ctty) {
93 if (ioctl(STDIN_FILENO, TIOCSCTTY, 1))
94 warn(_("failed to set the controlling terminal"));
95 }
96 execvp(argv[optind], argv + optind);
97 err(EXIT_FAILURE, _("execvp failed"));
98 }