]>
Commit | Line | Data |
---|---|---|
f092076f | 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 Daan De Meyer <daan.j.demeyer@gmail.com> | |
f092076f | 6 | */ |
f092076f DDM |
7 | #include <getopt.h> |
8 | #include <stdio.h> | |
9 | #include <stdlib.h> | |
10 | #include <unistd.h> | |
11 | #include <signal.h> | |
12 | ||
13 | #include "closestream.h" | |
14 | ||
15 | static void __attribute__((__noreturn__)) usage(void) | |
16 | { | |
17 | FILE *out = stdout; | |
18 | fputs(USAGE_HEADER, out); | |
19 | fprintf(out, _( | |
20 | " %s [options] <program> [arguments ...]\n"), | |
21 | program_invocation_short_name); | |
22 | ||
23 | fputs(USAGE_SEPARATOR, out); | |
24 | fputs(_("Run a program in a new process group.\n"), out); | |
25 | ||
26 | fputs(USAGE_OPTIONS, out); | |
27 | fputs(_(" -f, --foregound Make a foreground process group\n"), out); | |
28 | ||
bad4c729 | 29 | fprintf(out, USAGE_HELP_OPTIONS(16)); |
f092076f | 30 | |
bad4c729 | 31 | fprintf(out, USAGE_MAN_TAIL("setpgid(1)")); |
f092076f DDM |
32 | exit(EXIT_SUCCESS); |
33 | } | |
34 | ||
35 | int main(int argc, char **argv) | |
36 | { | |
37 | int ch, foreground = 0, fd; | |
38 | sigset_t s, old; | |
39 | ||
40 | static const struct option longopts[] = { | |
41 | {"foreground", no_argument, NULL, 'f'}, | |
42 | {"version", no_argument, NULL, 'V'}, | |
43 | {"help", no_argument, NULL, 'h'}, | |
44 | {NULL, 0, NULL, 0} | |
45 | }; | |
46 | ||
47 | setlocale(LC_ALL, ""); | |
48 | bindtextdomain(PACKAGE, LOCALEDIR); | |
49 | textdomain(PACKAGE); | |
50 | close_stdout_atexit(); | |
51 | ||
52 | while ((ch = getopt_long(argc, argv, "+Vh", longopts, NULL)) != -1) | |
53 | switch (ch) { | |
54 | case 'f': | |
55 | foreground = 1; | |
56 | break; | |
57 | case 'h': | |
58 | usage(); | |
59 | case 'V': | |
60 | print_version(EXIT_SUCCESS); | |
61 | default: | |
62 | errtryhelp(EXIT_FAILURE); | |
63 | } | |
64 | ||
65 | if (argc - optind < 1) { | |
66 | warnx(_("no command specified")); | |
67 | errtryhelp(EXIT_FAILURE); | |
68 | } | |
69 | ||
70 | if (setpgid(0, 0) < 0) | |
71 | err(EXIT_FAILURE, _("setpgid failed")); | |
72 | ||
73 | if (foreground) { | |
74 | fd = open("/dev/tty", O_RDONLY|O_CLOEXEC); | |
75 | if (fd >= 0) { | |
76 | if (sigemptyset(&s) < 0) | |
77 | err(EXIT_FAILURE, _("sigemptyset failed")); | |
78 | if (sigaddset(&s, SIGTTOU) < 0) | |
79 | err(EXIT_FAILURE, _("sigaddset failed")); | |
80 | if (sigprocmask(SIG_BLOCK, &s, &old) < 0) | |
81 | err(EXIT_FAILURE, _("sigprocmask failed")); | |
82 | if (tcsetpgrp(fd, getpgid(0)) < 0) | |
83 | err(EXIT_FAILURE, _("tcsetpgrp failed")); | |
84 | if (sigprocmask(SIG_SETMASK, &old, NULL) < 0) | |
85 | err(EXIT_FAILURE, _("sigprocmask failed")); | |
86 | } | |
87 | } | |
88 | ||
89 | execvp(argv[optind], argv + optind); | |
90 | errexec(argv[optind]); | |
91 | } |