示例#1
0
static void
CheckUtmp( void )
{
	static time_t modtim;
	time_t nck;
	time_t ends;
	struct utmps *utp, **utpp;
	struct stat st;
#ifdef BSD_UTMP
	int fd;
	struct utmp ut[1];
#else
	STRUCTUTMP *ut;
#endif

	if (!utmpList)
		return;
	if (stat( UTMP_FILE, &st )) {
		LogError( UTMP_FILE " not found - cannot use console mode\n" );
		bombUtmp();
		return;
	}
	if (modtim != st.st_mtime) {
		Debug( "rescanning " UTMP_FILE "\n" );
		for (utp = utmpList; utp; utp = utp->next)
			utp->state = UtDead;
#ifdef BSD_UTMP
		if ((fd = open( UTMP_FILE, O_RDONLY )) < 0) {
			LogError( "Cannot open " UTMP_FILE " - cannot use console mode\n" );
			bombUtmp();
			return;
		}
		while (Reader( fd, ut, sizeof(ut[0]) ) == sizeof(ut[0]))
#else
		SETUTENT();
		while ((ut = GETUTENT()))
#endif
		{
			for (utp = utmpList; utp; utp = utp->next) {
#ifdef HAVE_VTS
				char **line;
				for (line = consoleTTYs; *line; line++)
					if (!strncmp( *line, ut->ut_line, sizeof(ut->ut_line) ))
						goto hitlin;
				continue;
			  hitlin:
#else
				if (strncmp( utp->d->console, ut->ut_line, sizeof(ut->ut_line) ))
					continue;
#endif
#ifdef BSD_UTMP
				if (!*ut->ut_user) {
#else
				if (ut->ut_type != USER_PROCESS) {
#endif
#ifdef HAVE_VTS
					if (utp->state == UtActive)
						break;
#endif
					utp->state = UtWait;
				} else {
					utp->hadSess = 1;
					utp->state = UtActive;
				}
				if (utp->time < ut->ut_time) /* theoretically superfluous */
					utp->time = ut->ut_time;
				break;
			}
		}
#ifdef BSD_UTMP
		close( fd );
#else
		ENDUTENT();
#endif
		modtim = st.st_mtime;
	}
	for (utpp = &utmpList; (utp = *utpp); ) {
		if (utp->state != UtActive) {
			if (utp->state == UtDead) /* shouldn't happen ... */
				utp->time = 0;
			ends = utp->time + (utp->hadSess ? TIME_RELOG : TIME_LOG);
			if (ends <= now) {
#ifdef HAVE_VTS
				ForEachDisplay( WakeDisplay );
				Debug( "console login timed out\n" );
#else
				utp->d->status = notRunning;
				Debug( "console login for %s at %s timed out\n",
				       utp->d->name, utp->d->console );
#endif
				*utpp = utp->next;
				free( utp );
				continue;
			} else
				nck = ends;
		} else
			nck = TIME_RELOG + now;
		if (nck < utmpTimeout)
			utmpTimeout = nck;
		utpp = &(*utpp)->next;
	}
}

static void
#ifdef HAVE_VTS
SwitchToTty( void )
#else
SwitchToTty( struct display *d )
#endif
{
	struct utmps *utp;
#ifdef HAVE_VTS
	int vt;
#endif

	if (!(utp = Malloc( sizeof(*utp) ))) {
#ifdef HAVE_VTS
		ForEachDisplay( WakeDisplay );
#else
		d->status = notRunning;
#endif
		return;
	}
#ifndef HAVE_VTS
	d->status = textMode;
	utp->d = d;
#endif
	utp->time = now;
	utp->hadSess = 0;
	utp->next = utmpList;
	utmpList = utp;
	CheckUtmp();

#ifdef HAVE_VTS
	if ((vt = TTYtoVT( *consoleTTYs )))
		activateVT( vt );
#endif

	/* XXX output something useful here */
}

#ifdef HAVE_VTS
static void
StopToTTY( struct display *d )
{
	if ((d->displayType & d_location) == dLocal)
		switch (d->status) {
		default:
			rStopDisplay( d, DS_TEXTMODE | 0x100 );
		case reserve:
		case textMode:
			break;
		}
}

static void
CheckTTYMode( void )
{
	struct display *d;

	for (d = displays; d; d = d->next)
		if (d->status == zombie)
			return;

	SwitchToTty();
}

#else

void
SwitchToX( struct display *d )
{
	struct utmps *utp, **utpp;

	for (utpp = &utmpList; (utp = *utpp); utpp = &(*utpp)->next)
		if (utp->d == d) {
			*utpp = utp->next;
			free( utp );
			d->status = notRunning;
			return;
		}
}
#endif

#ifdef XDMCP
static void
StartRemoteLogin( struct display *d )
{
	char **argv;
	int pid;

	Debug( "StartRemoteLogin for %s\n", d->name );
	/* HACK: omitting LoadDisplayResources( d ) here! */
	switch (pid = Fork()) {
	case 0:
		argv = PrepServerArgv( d, d->serverArgsRemote );
		if (!(argv = addStrArr( argv, "-once", 5 )) ||
		    !(argv = addStrArr( argv, "-query", 6 )) ||
		    !(argv = addStrArr( argv, d->remoteHost, -1 )))
			exit( 1 );
		Debug( "exec %\"[s\n", argv );
		(void)execv( argv[0], argv );
		LogError( "X server %\"s cannot be executed\n", argv[0] );
		exit( 1 );
	case -1:
		LogError( "Forking X server for remote login failed: %m" );
		d->status = notRunning;
		return;
	default:
		break;
	}
	Debug( "X server forked, pid %d\n", pid );
	d->serverPid = pid;

	d->status = remoteLogin;
}
示例#2
0
文件: dm.c 项目: fluxer/kde-workspace
static void
checkUtmp(void)
{
    static time_t modtim;
    time_t nck;
    time_t ends;
    struct utmps *utp;
#ifndef HAVE_VTS
    struct utmps **utpp;
#endif
    struct stat st;
#ifdef BSD_UTMP
    int fd;
    struct utmp ut[1];
#else
    STRUCTUTMP *ut;
#endif

    if (!utmpList)
        return;
    if (stat(UTMP_FILE, &st)) {
        logError(UTMP_FILE " not found - cannot use console mode\n");
        wakeDisplays();
        return;
    }
    if (modtim != st.st_mtime) {
        debug("rescanning " UTMP_FILE "\n");
#ifdef HAVE_VTS
        utp = utmpList;
#else
        for (utp = utmpList; utp; utp = utp->next)
#endif
            utp->state = UtDead;
#ifdef BSD_UTMP
        if ((fd = open(UTMP_FILE, O_RDONLY)) < 0) {
            logError("Cannot open " UTMP_FILE " - cannot use console mode\n");
            wakeDisplays();
            return;
        }
        while (reader(fd, ut, sizeof(ut[0])) == sizeof(ut[0]))
#else
        SETUTENT();
        while ((ut = GETUTENT()))
#endif
        {
            /* first, match the tty to a utemps */
#ifdef HAVE_VTS
            char **line;
            for (line = consoleTTYs; *line; line++)
                if (!strncmp(*line, ut->ut_line, sizeof(ut->ut_line)))
#else
            for (utp = utmpList; utp; utp = utp->next)
                if (!strncmp(utp->d->console, ut->ut_line, sizeof(ut->ut_line)))
#endif
                    goto hitlin;
            continue;
          hitlin:
            /* then, update the utemps accordingly */
#ifdef BSD_UTMP
            if (!*ut->ut_user) {
#else
            if (ut->ut_type != USER_PROCESS) {
#endif
#ifdef HAVE_VTS
                /* don't allow "downgrading" the singular utemps */
                if (utp->state == UtActive)
                    continue;
#endif
                utp->state = UtWait;
            } else {
                utp->hadSess = True;
                utp->state = UtActive;
            }
            nck = ut->ut_time - nowWallDelta;
            if (nck > now)
                nck = 0; /* Clock jumped. Time out immediately. */
#ifdef HAVE_VTS
            /* tty with latest activity wins */
            if (utp->time < nck)
#endif
                utp->time = nck;
        }
#ifdef BSD_UTMP
        close(fd);
#else
        ENDUTENT();
#endif
        modtim = st.st_mtime;
    }
#ifdef HAVE_VTS
    utp = utmpList;
#else
    for (utpp = &utmpList; (utp = *utpp);) {
#endif
        if (utp->state != UtActive) {
            if (utp->state == UtDead) /* shouldn't happen ... */
                utp->time = 0;
            ends = utp->time + (utp->hadSess ? TIME_RELOG : TIME_LOG);
            if (ends <= now) {
#ifdef HAVE_VTS
                wakeDisplays();
                debug("console login timed out\n");
                return;
#else
                utp->d->status = notRunning;
                debug("console login for %s at %s timed out\n",
                       utp->d->name, utp->d->console);
                *utpp = utp->next;
                free(utp);
                continue;
#endif
            } else
                nck = ends;
        } else
            nck = TIME_RELOG + now;
        if (nck < utmpTimeout)
            utmpTimeout = nck;
#ifndef HAVE_VTS
        utpp = &(*utpp)->next;
    }
#endif
}

static void
#ifdef HAVE_VTS
switchToTTY(void)
#else
switchToTTY(struct display *d)
#endif
{
    struct utmps *utp;
#ifdef HAVE_VTS
    int vt;
#endif

    if (!(utp = Malloc(sizeof(*utp)))) {
#ifdef HAVE_VTS
        wakeDisplays();
#else
        d->status = notRunning;
#endif
        return;
    }
#ifndef HAVE_VTS
    d->status = textMode;
    utp->d = d;
    utp->next = utmpList;
#endif
    utp->time = now;
    utp->hadSess = False;
    utmpList = utp;
    checkUtmp();

#ifdef HAVE_VTS
    if ((vt = TTYtoVT(*consoleTTYs)))
        activateVT(vt);
#endif
}

#ifdef HAVE_VTS
static void
stopToTTY(struct display *d)
{
    if ((d->displayType & d_location) == dLocal)
        switch (d->status) {
        default:
            rStopDisplay(d, DS_TEXTMODE | DS_SCHEDULE);
        case reserve:
        case textMode:
            break;
        }
}

static void
checkTTYMode(void)
{
    struct display *d;

    for (d = displays; d; d = d->next)
        if (d->status == zombie)
            return;

    switchToTTY();
}

#else

void
switchToX(struct display *d)
{
    struct utmps *utp, **utpp;

    for (utpp = &utmpList; (utp = *utpp); utpp = &(*utpp)->next)
        if (utp->d == d) {
            *utpp = utp->next;
            free(utp);
            d->status = notRunning;
            return;
        }
}
#endif

#ifdef XDMCP
static void
startRemoteLogin(struct display *d)
{
    char **argv;

    debug("startRemoteLogin for %s\n", d->name);
    /* HACK: omitting loadDisplayResources(d) here! */
    switch (Fork(&d->serverPid)) {
    case 0:
        argv = prepareServerArgv(d, d->serverArgsRemote);
        if (!(argv = addStrArr(argv, "-once", 5)) ||
            !(argv = addStrArr(argv, "-query", 6)) ||
            !(argv = addStrArr(argv, d->remoteHost, -1)))
            exit(1);
        debug("exec %\"[s\n", argv);
        (void)execv(argv[0], argv);
        logError("X server %\"s cannot be executed\n", argv[0]);
        exit(1);
    case -1:
        logError("Forking X server for remote login failed: %m");
        d->status = notRunning;
        return;
    default:
        break;
    }
    debug("X server forked, pid %d\n", d->serverPid);

    d->status = remoteLogin;
}