LogoopenSUSE Build Service > Projects
Sign Up | Log In

View File setctsid.c of Package util-linux (Project Base:System)

/*
 * setctsid.c -- execute a command in a new session and with
 *		 new controlling terminal
 *
 * derviated from: setctsid.c of Rick Sladkey <jrs@world.std.com>
 *		   In the public domain.
 *
 * Changed by Werner Fink, <werner@suse.de>
 */

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/syslog.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>

#define xerror(n)	do { int error = errno; \
			     if (!isatty(fileno(stderr))) \
			       syslog(LOG_ERR, n ": %s", strerror(error)); \
			     else \
			       errno = error, perror(n); \
			} while (0)

int main(int argc, char *argv[])
{
	int fd;
	struct stat buf;
	int dofork = 0;

        if (argc > 1 && !strcmp(argv[1], "-f")) {
		dofork = 1;
		argc--;
		argv++;
	}
	if (argc < 3) {
		fprintf(stderr, "usage: setctsid [-f] tty program [arg ...]\n");
		exit(1);
	}
	if (stat(argv[1], &buf) < 0) {
		perror(argv[1]);
		exit(1);
	}
	if (!(S_ISCHR(buf.st_mode))) {
		/* why do we care? */
		fprintf(stderr, "%s: not a character device\n", argv[1]);
		exit(1);
	}
	if (dofork) {
		switch (fork()) {
		case -1:
			perror("fork");
			exit(1);
		case 0:
			break;
		default:
			exit(0);
		}
	}
	if (setsid() < 0) {
		perror("setsid");
		exit(1);
	}
	if ((fd = open(argv[1], O_RDWR, 0)) < 0) {
		xerror("open");
		exit(1);
	}
	dup2(fd, fileno(stdin));
	dup2(fd, fileno(stdout));
	dup2(fd, fileno(stderr));

	if (isatty(fd)) {
		if (ioctl(fileno(stdin), TIOCSCTTY, argv[1]) < 0) {
			xerror("ioctl");
			exit(1);
		}
	}

	if (fd > fileno(stderr))
		close(fd);

	execvp(argv[2], argv + 2);
	xerror("execvp");
	exit(1);
}