forget difference between big and small commands - obsolete with vm.
[minix.git] / commands / simple / intr.c
blobf858cdb4f94e3d5a2a198a4258d7e26ec1c9ac75
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>
18 #if __minix
19 static char DEV_LOG[]= "/dev/log";
20 #else
21 static char DEV_LOG[]= "/dev/console";
22 #endif
24 static void say(const char *s)
26 write(2, s, strlen(s));
29 static void fatal(const char *label)
31 int err= errno;
33 say("intr: ");
34 say(label);
35 say(": ");
36 say(strerror(err));
37 say("\n");
38 exit(1);
41 static void usage(void)
43 say("Usage: intr [-d] [-t seconds] command [arg ...]\n");
44 exit(1);
47 int main(int argc, char **argv)
49 int fd;
50 unsigned n= 0;
51 int daemonize= 0;
52 int i;
54 i= 1;
55 while (i < argc && argv[i][0] == '-') {
56 char *opt= argv[i++]+1, *end;
57 unsigned long sec;
59 if (opt[0] == '-' && opt[1] == 0) break;
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++];
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();
82 if ((argc - i) < 1) usage();
84 /* Try to open the controlling tty. */
85 if ((fd= open("/dev/tty", O_RDWR)) < 0) {
86 if (errno != ENXIO) fatal("/dev/tty");
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.
94 if (fd < 0) {
95 if (setsid() < 0) fatal("setsid()");
97 fd= open("/dev/console", O_RDWR);
100 if (fd >= 0) {
101 if (fd != 0) {
102 dup2(fd, 0);
103 close(fd);
105 dup2(0, 1);
106 dup2(0, 2);
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.
118 if (fd >= 0) {
119 close(fd);
121 if (setsid() < 0) fatal("setsid()");
123 if ((fd= open("/dev/null", O_RDWR)) < 0) fatal("/dev/null");
124 if (fd != 0) {
125 dup2(fd, 0);
126 close(fd);
128 if ((fd= open(DEV_LOG, O_WRONLY)) < 0) fatal(DEV_LOG);
129 if (fd != 1) {
130 dup2(fd, 1);
131 close(fd);
133 dup2(1, 2);
135 /* Move to the root directory. */
136 (void) chdir("/");
139 /* Schedule the alarm. (It is inherited over execve.) */
140 if (n != 0) alarm(n);
142 /* Call program. */
143 execvp(argv[i], argv + i);
145 /* Complain. */
146 fatal(argv[i]);
147 return 0;