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 24 static void say(const char *s) 25 { 26 write(2, s, strlen(s)); 27 } 28 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 41 static void usage(void) 42 { 43 say("Usage: intr [-d] [-t seconds] command [arg ...]\n"); 44 exit(1); 45 } 46 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