149 lines
2.7 KiB
C
149 lines
2.7 KiB
C
/* intr 1.4 - run a command with interrupts enabled
|
|
* Author: Kees J. Bot
|
|
* 17 Dec 1992
|
|
*/
|
|
#define nil 0
|
|
#ifndef _POSIX_SOURCE
|
|
#define _POSIX_SOURCE 1
|
|
#endif
|
|
#include <sys/types.h>
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <signal.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
#if __minix
|
|
static char DEV_LOG[]= "/dev/log";
|
|
#else
|
|
static char DEV_LOG[]= "/dev/console";
|
|
#endif
|
|
|
|
static void say(const char *s)
|
|
{
|
|
write(2, s, strlen(s));
|
|
}
|
|
|
|
static void fatal(const char *label)
|
|
{
|
|
int err= errno;
|
|
|
|
say("intr: ");
|
|
say(label);
|
|
say(": ");
|
|
say(strerror(err));
|
|
say("\n");
|
|
exit(1);
|
|
}
|
|
|
|
static void usage(void)
|
|
{
|
|
say("Usage: intr [-d] [-t seconds] command [arg ...]\n");
|
|
exit(1);
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
int fd;
|
|
unsigned n= 0;
|
|
int daemonize= 0;
|
|
int i;
|
|
|
|
i= 1;
|
|
while (i < argc && argv[i][0] == '-') {
|
|
char *opt= argv[i++]+1, *end;
|
|
unsigned long sec;
|
|
|
|
if (opt[0] == '-' && opt[1] == 0) break;
|
|
|
|
while (*opt != 0) switch (*opt++) {
|
|
case 'd':
|
|
/* -d */
|
|
daemonize= 1;
|
|
break;
|
|
case 't':
|
|
/* -t n: alarm in n seconds. */
|
|
if (*opt == 0) {
|
|
if (i == argc) usage();
|
|
opt= argv[i++];
|
|
}
|
|
sec= strtoul(opt, &end, 10);
|
|
if (end == opt || *end != 0 || (n= sec) != sec)
|
|
usage();
|
|
opt= "";
|
|
break;
|
|
default:
|
|
usage();
|
|
}
|
|
}
|
|
|
|
if ((argc - i) < 1) usage();
|
|
|
|
/* Try to open the controlling tty. */
|
|
if ((fd= open("/dev/tty", O_RDWR)) < 0) {
|
|
if (errno != ENXIO) fatal("/dev/tty");
|
|
}
|
|
|
|
if (!daemonize) {
|
|
/* Bring to the foreground. If we already have a controlling
|
|
* tty then use it. Otherwise try to allocate the console as
|
|
* controlling tty and begin a process group.
|
|
*/
|
|
if (fd < 0) {
|
|
if (setsid() < 0) fatal("setsid()");
|
|
|
|
fd= open("/dev/console", O_RDWR);
|
|
}
|
|
|
|
if (fd >= 0) {
|
|
if (fd != 0) {
|
|
dup2(fd, 0);
|
|
close(fd);
|
|
}
|
|
dup2(0, 1);
|
|
dup2(0, 2);
|
|
}
|
|
|
|
/* Set the usual signals back to the default. */
|
|
signal(SIGHUP, SIG_DFL);
|
|
signal(SIGINT, SIG_DFL);
|
|
signal(SIGQUIT, SIG_DFL);
|
|
signal(SIGTERM, SIG_DFL);
|
|
} else {
|
|
/* Send to the background. Redirect input to /dev/null, and
|
|
* output to the log device. Detach from the process group.
|
|
*/
|
|
if (fd >= 0) {
|
|
close(fd);
|
|
|
|
if (setsid() < 0) fatal("setsid()");
|
|
}
|
|
if ((fd= open("/dev/null", O_RDWR)) < 0) fatal("/dev/null");
|
|
if (fd != 0) {
|
|
dup2(fd, 0);
|
|
close(fd);
|
|
}
|
|
if ((fd= open(DEV_LOG, O_WRONLY)) < 0) fatal(DEV_LOG);
|
|
if (fd != 1) {
|
|
dup2(fd, 1);
|
|
close(fd);
|
|
}
|
|
dup2(1, 2);
|
|
|
|
/* Move to the root directory. */
|
|
(void) chdir("/");
|
|
}
|
|
|
|
/* Schedule the alarm. (It is inherited over execve.) */
|
|
if (n != 0) alarm(n);
|
|
|
|
/* Call program. */
|
|
execvp(argv[i], argv + i);
|
|
|
|
/* Complain. */
|
|
fatal(argv[i]);
|
|
return 0;
|
|
}
|