xref: /minix3/minix/commands/intr/intr.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
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