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