1*433d6423SLionel Sambuc /* intr 1.4 - run a command with interrupts enabled
2*433d6423SLionel Sambuc * Author: Kees J. Bot
3*433d6423SLionel Sambuc * 17 Dec 1992
4*433d6423SLionel Sambuc */
5*433d6423SLionel Sambuc #define nil 0
6*433d6423SLionel Sambuc #ifndef _POSIX_SOURCE
7*433d6423SLionel Sambuc #define _POSIX_SOURCE 1
8*433d6423SLionel Sambuc #endif
9*433d6423SLionel Sambuc #include <sys/types.h>
10*433d6423SLionel Sambuc #include <errno.h>
11*433d6423SLionel Sambuc #include <fcntl.h>
12*433d6423SLionel Sambuc #include <signal.h>
13*433d6423SLionel Sambuc #include <stdio.h>
14*433d6423SLionel Sambuc #include <stdlib.h>
15*433d6423SLionel Sambuc #include <string.h>
16*433d6423SLionel Sambuc #include <unistd.h>
17*433d6423SLionel Sambuc
18*433d6423SLionel Sambuc #if __minix
19*433d6423SLionel Sambuc static char DEV_LOG[]= "/dev/log";
20*433d6423SLionel Sambuc #else
21*433d6423SLionel Sambuc static char DEV_LOG[]= "/dev/console";
22*433d6423SLionel Sambuc #endif
23*433d6423SLionel Sambuc
say(const char * s)24*433d6423SLionel Sambuc static void say(const char *s)
25*433d6423SLionel Sambuc {
26*433d6423SLionel Sambuc write(2, s, strlen(s));
27*433d6423SLionel Sambuc }
28*433d6423SLionel Sambuc
fatal(const char * label)29*433d6423SLionel Sambuc static void fatal(const char *label)
30*433d6423SLionel Sambuc {
31*433d6423SLionel Sambuc int err= errno;
32*433d6423SLionel Sambuc
33*433d6423SLionel Sambuc say("intr: ");
34*433d6423SLionel Sambuc say(label);
35*433d6423SLionel Sambuc say(": ");
36*433d6423SLionel Sambuc say(strerror(err));
37*433d6423SLionel Sambuc say("\n");
38*433d6423SLionel Sambuc exit(1);
39*433d6423SLionel Sambuc }
40*433d6423SLionel Sambuc
usage(void)41*433d6423SLionel Sambuc static void usage(void)
42*433d6423SLionel Sambuc {
43*433d6423SLionel Sambuc say("Usage: intr [-d] [-t seconds] command [arg ...]\n");
44*433d6423SLionel Sambuc exit(1);
45*433d6423SLionel Sambuc }
46*433d6423SLionel Sambuc
main(int argc,char ** argv)47*433d6423SLionel Sambuc int main(int argc, char **argv)
48*433d6423SLionel Sambuc {
49*433d6423SLionel Sambuc int fd;
50*433d6423SLionel Sambuc unsigned n= 0;
51*433d6423SLionel Sambuc int daemonize= 0;
52*433d6423SLionel Sambuc int i;
53*433d6423SLionel Sambuc
54*433d6423SLionel Sambuc i= 1;
55*433d6423SLionel Sambuc while (i < argc && argv[i][0] == '-') {
56*433d6423SLionel Sambuc char *opt= argv[i++]+1, *end;
57*433d6423SLionel Sambuc unsigned long sec;
58*433d6423SLionel Sambuc
59*433d6423SLionel Sambuc if (opt[0] == '-' && opt[1] == 0) break;
60*433d6423SLionel Sambuc
61*433d6423SLionel Sambuc while (*opt != 0) switch (*opt++) {
62*433d6423SLionel Sambuc case 'd':
63*433d6423SLionel Sambuc /* -d */
64*433d6423SLionel Sambuc daemonize= 1;
65*433d6423SLionel Sambuc break;
66*433d6423SLionel Sambuc case 't':
67*433d6423SLionel Sambuc /* -t n: alarm in n seconds. */
68*433d6423SLionel Sambuc if (*opt == 0) {
69*433d6423SLionel Sambuc if (i == argc) usage();
70*433d6423SLionel Sambuc opt= argv[i++];
71*433d6423SLionel Sambuc }
72*433d6423SLionel Sambuc sec= strtoul(opt, &end, 10);
73*433d6423SLionel Sambuc if (end == opt || *end != 0 || (n= sec) != sec)
74*433d6423SLionel Sambuc usage();
75*433d6423SLionel Sambuc opt= "";
76*433d6423SLionel Sambuc break;
77*433d6423SLionel Sambuc default:
78*433d6423SLionel Sambuc usage();
79*433d6423SLionel Sambuc }
80*433d6423SLionel Sambuc }
81*433d6423SLionel Sambuc
82*433d6423SLionel Sambuc if ((argc - i) < 1) usage();
83*433d6423SLionel Sambuc
84*433d6423SLionel Sambuc /* Try to open the controlling tty. */
85*433d6423SLionel Sambuc if ((fd= open("/dev/tty", O_RDWR)) < 0) {
86*433d6423SLionel Sambuc if (errno != ENXIO) fatal("/dev/tty");
87*433d6423SLionel Sambuc }
88*433d6423SLionel Sambuc
89*433d6423SLionel Sambuc if (!daemonize) {
90*433d6423SLionel Sambuc /* Bring to the foreground. If we already have a controlling
91*433d6423SLionel Sambuc * tty then use it. Otherwise try to allocate the console as
92*433d6423SLionel Sambuc * controlling tty and begin a process group.
93*433d6423SLionel Sambuc */
94*433d6423SLionel Sambuc if (fd < 0) {
95*433d6423SLionel Sambuc if (setsid() < 0) fatal("setsid()");
96*433d6423SLionel Sambuc
97*433d6423SLionel Sambuc fd= open("/dev/console", O_RDWR);
98*433d6423SLionel Sambuc }
99*433d6423SLionel Sambuc
100*433d6423SLionel Sambuc if (fd >= 0) {
101*433d6423SLionel Sambuc if (fd != 0) {
102*433d6423SLionel Sambuc dup2(fd, 0);
103*433d6423SLionel Sambuc close(fd);
104*433d6423SLionel Sambuc }
105*433d6423SLionel Sambuc dup2(0, 1);
106*433d6423SLionel Sambuc dup2(0, 2);
107*433d6423SLionel Sambuc }
108*433d6423SLionel Sambuc
109*433d6423SLionel Sambuc /* Set the usual signals back to the default. */
110*433d6423SLionel Sambuc signal(SIGHUP, SIG_DFL);
111*433d6423SLionel Sambuc signal(SIGINT, SIG_DFL);
112*433d6423SLionel Sambuc signal(SIGQUIT, SIG_DFL);
113*433d6423SLionel Sambuc signal(SIGTERM, SIG_DFL);
114*433d6423SLionel Sambuc } else {
115*433d6423SLionel Sambuc /* Send to the background. Redirect input to /dev/null, and
116*433d6423SLionel Sambuc * output to the log device. Detach from the process group.
117*433d6423SLionel Sambuc */
118*433d6423SLionel Sambuc if (fd >= 0) {
119*433d6423SLionel Sambuc close(fd);
120*433d6423SLionel Sambuc
121*433d6423SLionel Sambuc if (setsid() < 0) fatal("setsid()");
122*433d6423SLionel Sambuc }
123*433d6423SLionel Sambuc if ((fd= open("/dev/null", O_RDWR)) < 0) fatal("/dev/null");
124*433d6423SLionel Sambuc if (fd != 0) {
125*433d6423SLionel Sambuc dup2(fd, 0);
126*433d6423SLionel Sambuc close(fd);
127*433d6423SLionel Sambuc }
128*433d6423SLionel Sambuc if ((fd= open(DEV_LOG, O_WRONLY)) < 0) fatal(DEV_LOG);
129*433d6423SLionel Sambuc if (fd != 1) {
130*433d6423SLionel Sambuc dup2(fd, 1);
131*433d6423SLionel Sambuc close(fd);
132*433d6423SLionel Sambuc }
133*433d6423SLionel Sambuc dup2(1, 2);
134*433d6423SLionel Sambuc
135*433d6423SLionel Sambuc /* Move to the root directory. */
136*433d6423SLionel Sambuc (void) chdir("/");
137*433d6423SLionel Sambuc }
138*433d6423SLionel Sambuc
139*433d6423SLionel Sambuc /* Schedule the alarm. (It is inherited over execve.) */
140*433d6423SLionel Sambuc if (n != 0) alarm(n);
141*433d6423SLionel Sambuc
142*433d6423SLionel Sambuc /* Call program. */
143*433d6423SLionel Sambuc execvp(argv[i], argv + i);
144*433d6423SLionel Sambuc
145*433d6423SLionel Sambuc /* Complain. */
146*433d6423SLionel Sambuc fatal(argv[i]);
147*433d6423SLionel Sambuc return 0;
148*433d6423SLionel Sambuc }
149