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; }
/* Search utmp for the local user */ int find_user (char *name, char *tty) { UTMP *uptr; int status; struct stat statb; char ftty[sizeof (PATH_DEV) + sizeof (uptr->ut_line)]; time_t last_time = 0; int notty; notty = (*tty == '\0'); status = NOT_HERE; strcpy(ftty, PATH_DEV); SETUTENT (); while ((uptr = GETUTENT ()) != NULL) { #ifdef USER_PROCESS if (uptr->ut_type != USER_PROCESS) continue; #endif if (!strncmp (uptr->ut_name, name, sizeof(uptr->ut_name))) { if (notty) { /* no particular tty was requested */ strncpy(ftty + sizeof(PATH_DEV) - 1, uptr->ut_line, sizeof(ftty) - sizeof(PATH_DEV) - 1); ftty[sizeof(ftty) - 1] = 0; if (stat(ftty, &statb) == 0) { if (!(statb.st_mode & S_IWGRP)) { if (status != SUCCESS) status = PERMISSION_DENIED; continue; } if (statb.st_atime > last_time) { last_time = statb.st_atime; strcpy(tty, uptr->ut_line); status = SUCCESS; } continue; } } if (!strcmp(uptr->ut_line, tty)) { status = SUCCESS; break; } } } ENDUTENT (); return status; }
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; }
void ListSessions(int flags, struct display *d, void *ctx, void (*emitXSess)(struct display *, struct display *, void *), void (*emitTTYSess)(STRUCTUTMP *, struct display *, void *)) { struct display *di; #ifdef IP6_MAGIC int le, dot; #endif #ifdef BSD_UTMP int fd; struct utmp ut[1]; #else STRUCTUTMP *ut; #endif for(di = displays; di; di = di->next) if(((flags & lstRemote) || (di->displayType & d_location) == dLocal) && (di->status == remoteLogin || ((flags & lstPassive) ? di->status == running : di->userSess >= 0))) emitXSess(di, d, ctx); if(!(flags & lstTTY)) return; #ifdef BSD_UTMP if((fd = open(UTMP_FILE, O_RDONLY)) < 0) return; while(Reader(fd, ut, sizeof(ut[0])) == sizeof(ut[0])) { if(*ut->ut_user) { /* no idea how to list passive TTYs on BSD */ #else SETUTENT(); while((ut = GETUTENT())) { if(ut->ut_type == USER_PROCESS #if 0 /* list passive TTYs at all? not too sensible, i think. */ || ((flags & lstPassive) && ut->ut_type == LOGIN_PROCESS) #endif ) { #endif if(*ut->ut_host) { /* from remote or x */ if(!(flags & lstRemote)) continue; } else { /* hack around broken konsole which does not set ut_host. */ /* this check is probably linux-specific. */ /* alternatively we could open the device and try VT_OPENQRY. */ if(memcmp(ut->ut_line, "tty", 3) || !isdigit(ut->ut_line[3])) continue; } if(StrNChrCnt(ut->ut_line, sizeof(ut->ut_line), ':')) continue; /* x login */ switch(StrNChrCnt(ut->ut_host, sizeof(ut->ut_host), ':')) { case 1: /* x terminal */ continue; default: #ifdef IP6_MAGIC /* unknown - IPv6 makes things complicated */ le = StrNLen(ut->ut_host, sizeof(ut->ut_host)); /* cut off screen number */ for(dot = le; ut->ut_host[--dot] != ':';) if(ut->ut_host[dot] == '.') { le = dot; break; } for(di = displays; di; di = di->next) if(!memcmp(di->name, ut->ut_host, le) && !di->name[le]) goto cont; /* x terminal */ break; cont: continue; case 0: /* no x terminal */ #endif break; } emitTTYSess(ut, d, ctx); } } #ifdef BSD_UTMP close(fd); #else ENDUTENT(); #endif }