Revision 7a16363389b0026609141d50b71c40a298b11939 authored by chou86_e on 10 January 2008, 03:22:31 UTC, committed by chou86_e on 10 January 2008, 03:22:31 UTC
Yield() is used for window manager to put events on the queue so
logoEventManager->ProcessAnEvent() can handle it.


git-svn-id: https://svn.code.sf.net/p/ucblogo/code@50 fc4ef4ee-df3e-0410-84de-fb01f5d6c4f7
1 parent 7938cdc
Raw File
pseudo.cpp

// Copyright Timothy Miller, 1999

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <grp.h>
#include <string.h>
#include <signal.h>
#include <sys/time.h>
#include <pwd.h>
#include <utmp.h>
#include <stdlib.h>

int master_fd;

static char pty_name[12];
static int uid, gid;

void remove_utmp();
void add_utmp(int);

int pty_master()
{
	int i, mfd;
	char *ptr;
	struct stat statbuf;
	static char ptychar[] = "pqrstuvwxyzPQRST";
	static char hexdigit[] = "0123456789abcdef";

	for (ptr = ptychar; *ptr; ptr++) {
		strcpy(pty_name, "/dev/ptyXY");
		pty_name[8] = *ptr;
		pty_name[9] = '0';

		if (stat(pty_name, &statbuf) < 0) break;

		for (i=0; i<16; i++) {
			pty_name[9] = hexdigit[i];
			mfd = open(pty_name, O_RDWR);
			if (mfd >= 0) return mfd;
		}
	}
	return -1;
}

int pty_slave()
{
	int i, sfd;
	struct group *gptr;
	int gid;

	if ((gptr = getgrnam("tty")) != 0) {
		gid = gptr->gr_gid;
	} else {
		gid = -1;
	}

	chown(pty_name, getuid(), gid);
	chmod(pty_name, S_IRUSR|S_IWUSR|S_IWGRP);

	sfd = open(pty_name, O_RDWR);
	return sfd;
}

struct stat tty_stat;

int spawn(char *exe)
{
	int mfd, pid, sfd, fd, i;
	int uid, gid;

	uid = getuid();
	gid = getgid();

	mfd = pty_master();

	if (mfd < 0) {
		fprintf(stderr, "Can't open master\n");
		return -1;
	}

        pty_name[5] = 't';
	stat(pty_name, &tty_stat);

	pid = fork();
	if (pid<0) {
		fprintf(stderr, "Can't fork\n");
		return -1;
	}

	if (!pid) {
		close(mfd);

		sfd = pty_slave();
		if (sfd<0) {
			fprintf(stderr, "Can't open child\n");
			return -1;
		}

		setuid(uid);
		setgid(gid);

		if (setsid()<0) 
			fprintf(stderr, "Could not set session leader\n");
		if (ioctl(sfd, TIOCSCTTY, NULL)) 
			fprintf(stderr, "Could not set controllint tty\n");

		dup2(sfd, 0);
		dup2(sfd, 1);
		dup2(sfd, 2);
		if (sfd>2) close(sfd);

		execl(exe, exe, NULL);
		exit(0);
	}

	add_utmp(pid);

	master_fd = mfd;
	return mfd;
}

void restore_ttyp()
{
	chown(pty_name, tty_stat.st_uid, tty_stat.st_gid);
	chmod(pty_name, tty_stat.st_mode);

	remove_utmp();
}

struct utmp ut_entry;

void add_utmp(int spid)
{

	ut_entry.ut_type = USER_PROCESS;
	ut_entry.ut_pid = spid;
	strcpy(ut_entry.ut_line, pty_name+5);
	strcpy(ut_entry.ut_id, pty_name+8);
	time(&ut_entry.ut_time);
	strcpy(ut_entry.ut_user, getpwuid(getuid())->pw_name);
	strcpy(ut_entry.ut_host, getenv("DISPLAY"));
	ut_entry.ut_addr = 0;
	setutent();
	pututline(&ut_entry);
	endutent();
}

void remove_utmp()
{
	ut_entry.ut_type = DEAD_PROCESS;
	memset(ut_entry.ut_line, 0, UT_LINESIZE);
	ut_entry.ut_time = 0;
	memset(ut_entry.ut_user, 0, UT_NAMESIZE);
	setutent();
	pututline(&ut_entry);
	endutent();
}

back to top