mirror of
https://bitbucket.org/smil3y/kde-workspace.git
synced 2025-02-24 19:02:51 +00:00
791 lines
17 KiB
C
791 lines
17 KiB
C
![]() |
/*
|
||
|
|
||
|
Copyright 1989, 1998 The Open Group
|
||
|
Copyright 2000-2005 Oswald Buddenhagen <ossi@kde.org>
|
||
|
|
||
|
Permission to use, copy, modify, distribute, and sell this software and its
|
||
|
documentation for any purpose is hereby granted without fee, provided that
|
||
|
the above copyright notice appear in all copies and that both that
|
||
|
copyright notice and this permission notice appear in supporting
|
||
|
documentation.
|
||
|
|
||
|
The above copyright notice and this permission notice shall be included
|
||
|
in all copies or substantial portions of the Software.
|
||
|
|
||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||
|
IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||
|
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||
|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||
|
OTHER DEALINGS IN THE SOFTWARE.
|
||
|
|
||
|
Except as contained in this notice, the name of a copyright holder shall
|
||
|
not be used in advertising or otherwise to promote the sale, use or
|
||
|
other dealings in this Software without prior written authorization
|
||
|
from the copyright holder.
|
||
|
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
* xdm - display manager daemon
|
||
|
* Author: Keith Packard, MIT X Consortium
|
||
|
*
|
||
|
* various utility routines
|
||
|
*/
|
||
|
|
||
|
#include "dm.h"
|
||
|
#include "dm_auth.h"
|
||
|
#include "dm_error.h"
|
||
|
|
||
|
#include <string.h>
|
||
|
#include <unistd.h>
|
||
|
#include <pwd.h>
|
||
|
#include <ctype.h>
|
||
|
#include <sys/types.h>
|
||
|
#include <sys/stat.h>
|
||
|
#include <signal.h>
|
||
|
|
||
|
#ifdef NEED_UTSNAME
|
||
|
# include <sys/utsname.h>
|
||
|
#endif
|
||
|
|
||
|
void *
|
||
|
Calloc(size_t nmemb, size_t size)
|
||
|
{
|
||
|
void *ret;
|
||
|
|
||
|
if (!(ret = calloc(nmemb, size)))
|
||
|
logOutOfMem();
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
void *
|
||
|
Malloc(size_t size)
|
||
|
{
|
||
|
void *ret;
|
||
|
|
||
|
if (!(ret = malloc(size)))
|
||
|
logOutOfMem();
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
void *
|
||
|
Realloc(void *ptr, size_t size)
|
||
|
{
|
||
|
void *ret;
|
||
|
|
||
|
if (!(ret = realloc(ptr, size)) && size)
|
||
|
logOutOfMem();
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
strCatL(char **bp, const char *str, int max)
|
||
|
{
|
||
|
int dnl = strnlen(str, max);
|
||
|
memcpy(*bp, str, dnl);
|
||
|
*bp += dnl;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
strCat(char **bp, const char *str)
|
||
|
{
|
||
|
int dnl = strlen(str);
|
||
|
memcpy(*bp, str, dnl);
|
||
|
*bp += dnl;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
strCmp(const char *s1, const char *s2)
|
||
|
{
|
||
|
if (s1 == s2)
|
||
|
return 0;
|
||
|
if (!s1)
|
||
|
return -1;
|
||
|
if (!s2)
|
||
|
return 1;
|
||
|
return strcmp(s1, s2);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
wipeStr(char *str)
|
||
|
{
|
||
|
if (str) {
|
||
|
bzero(str, strlen(str));
|
||
|
free(str);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#ifndef HAVE_STRNLEN
|
||
|
int
|
||
|
strnlen(const char *s, int max)
|
||
|
{
|
||
|
unsigned l;
|
||
|
|
||
|
for (l = 0; l < (unsigned)max && s[l]; l++);
|
||
|
return l;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
/* duplicate src; wipe & free old dst string */
|
||
|
int
|
||
|
reStrN(char **dst, const char *src, int len)
|
||
|
{
|
||
|
char *ndst = 0;
|
||
|
|
||
|
if (src) {
|
||
|
if (len < 0)
|
||
|
len = strlen(src);
|
||
|
if (*dst && !memcmp(*dst, src, len) && !(*dst)[len])
|
||
|
return 1;
|
||
|
if (!(ndst = Malloc(len + 1))) {
|
||
|
wipeStr(*dst);
|
||
|
*dst = 0;
|
||
|
return 0;
|
||
|
}
|
||
|
memcpy(ndst, src, len);
|
||
|
ndst[len] = 0;
|
||
|
}
|
||
|
wipeStr(*dst); /* make an option, if we should become heavily used */
|
||
|
*dst = ndst;
|
||
|
return 2;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
reStr(char **dst, const char *src)
|
||
|
{
|
||
|
return reStrN(dst, src, -1);
|
||
|
}
|
||
|
|
||
|
/* duplicate src */
|
||
|
int
|
||
|
strNDup(char **dst, const char *src, int len)
|
||
|
{
|
||
|
if (src) {
|
||
|
if (len < 0)
|
||
|
len = strlen(src);
|
||
|
if (!(*dst = Malloc(len + 1)))
|
||
|
return False;
|
||
|
memcpy(*dst, src, len);
|
||
|
(*dst)[len] = 0;
|
||
|
} else {
|
||
|
*dst = 0;
|
||
|
}
|
||
|
return True;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
strDup(char **dst, const char *src)
|
||
|
{
|
||
|
return strNDup(dst, src, -1);
|
||
|
}
|
||
|
|
||
|
char *
|
||
|
replaceInString(const char *str, const char *before, const char *after)
|
||
|
{
|
||
|
int len;
|
||
|
size_t beforeLen = strlen(before), afterLen = strlen(after);
|
||
|
char *buf, *ret;
|
||
|
const char *ptr;
|
||
|
|
||
|
for (ptr = str, len = 0; (ptr = strstr(ptr, before)); len++)
|
||
|
ptr += beforeLen;
|
||
|
len = strlen(str) + (afterLen - beforeLen) * len;
|
||
|
|
||
|
if (!(buf = ret = Malloc(len + 1)))
|
||
|
return 0;
|
||
|
|
||
|
for (ptr = str; (str = strstr(str, before)); str += beforeLen, ptr = str) {
|
||
|
strCatL(&buf, ptr, str - ptr);
|
||
|
strCatL(&buf, after, afterLen);
|
||
|
}
|
||
|
strcpy(buf, ptr);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
/* append any number of strings to dst */
|
||
|
int
|
||
|
strApp(char **dst, ...)
|
||
|
{
|
||
|
int len;
|
||
|
char *bk, *pt, *dp;
|
||
|
va_list va;
|
||
|
|
||
|
len = 1;
|
||
|
if (*dst)
|
||
|
len += strlen(*dst);
|
||
|
va_start(va, dst);
|
||
|
for (;;) {
|
||
|
pt = va_arg(va, char *);
|
||
|
if (!pt)
|
||
|
break;
|
||
|
len += strlen(pt);
|
||
|
}
|
||
|
va_end(va);
|
||
|
if (!(bk = Malloc(len))) {
|
||
|
free(*dst);
|
||
|
*dst = 0;
|
||
|
return False;
|
||
|
}
|
||
|
dp = bk;
|
||
|
if (*dst) {
|
||
|
len = strlen(*dst);
|
||
|
memcpy(dp, *dst, len);
|
||
|
dp += len;
|
||
|
free(*dst);
|
||
|
}
|
||
|
va_start(va, dst);
|
||
|
for (;;) {
|
||
|
pt = va_arg(va, char *);
|
||
|
if (!pt)
|
||
|
break;
|
||
|
len = strlen(pt);
|
||
|
memcpy(dp, pt, len);
|
||
|
dp += len;
|
||
|
}
|
||
|
va_end(va);
|
||
|
*dp = '\0';
|
||
|
*dst = bk;
|
||
|
return True;
|
||
|
}
|
||
|
|
||
|
char *
|
||
|
expandMacros(const char *str, struct expando *expandos)
|
||
|
{
|
||
|
struct expando *ex;
|
||
|
int cnt = 0, rcnt, vl;
|
||
|
const char *sp = str;
|
||
|
char *ret, *cp;
|
||
|
char c;
|
||
|
|
||
|
oke1:
|
||
|
while ((c = *sp++)) {
|
||
|
if (c == '%') {
|
||
|
rcnt = 0;
|
||
|
for (;;) {
|
||
|
c = *sp++;
|
||
|
if (!c)
|
||
|
goto murks1;
|
||
|
if (c == '%')
|
||
|
break;
|
||
|
for (ex = expandos; ex->key; ex++)
|
||
|
if (c == ex->key) {
|
||
|
if (ex->val)
|
||
|
cnt += strlen(ex->val) + rcnt;
|
||
|
goto oke1;
|
||
|
}
|
||
|
rcnt++;
|
||
|
}
|
||
|
}
|
||
|
cnt++;
|
||
|
}
|
||
|
murks1:
|
||
|
if (!(cp = ret = Malloc(cnt + 1)))
|
||
|
return 0;
|
||
|
oke2:
|
||
|
while ((c = *str++)) {
|
||
|
if (c == '%') {
|
||
|
rcnt = 0;
|
||
|
for (;;) {
|
||
|
c = *str++;
|
||
|
if (!c)
|
||
|
goto murks2;
|
||
|
if (c == '%')
|
||
|
break;
|
||
|
for (ex = expandos; ex->key; ex++)
|
||
|
if (c == ex->key) {
|
||
|
if (ex->val) {
|
||
|
vl = strlen(ex->val);
|
||
|
memcpy(cp, str - 1 - rcnt, rcnt);
|
||
|
memcpy(cp + rcnt, ex->val, vl);
|
||
|
cp += vl + rcnt;
|
||
|
}
|
||
|
ex->uses++;
|
||
|
goto oke2;
|
||
|
}
|
||
|
rcnt++;
|
||
|
}
|
||
|
}
|
||
|
*cp++ = c;
|
||
|
}
|
||
|
murks2:
|
||
|
*cp = 0;
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
|
||
|
char **
|
||
|
initStrArr(char **arr)
|
||
|
{
|
||
|
if (!arr && (arr = Malloc(sizeof(char *))))
|
||
|
arr[0] = 0;
|
||
|
return arr;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
arrLen(char **arr)
|
||
|
{
|
||
|
int nu = 0;
|
||
|
if (arr)
|
||
|
for (; arr[nu]; nu++);
|
||
|
return nu;
|
||
|
}
|
||
|
|
||
|
char **
|
||
|
extStrArr(char **arr, char ***strp)
|
||
|
{
|
||
|
char **rarr;
|
||
|
int nu;
|
||
|
|
||
|
nu = arrLen(arr);
|
||
|
if ((rarr = Realloc(arr, sizeof(char *) * (nu + 2)))) {
|
||
|
rarr[nu + 1] = 0;
|
||
|
*strp = rarr + nu;
|
||
|
return rarr;
|
||
|
}
|
||
|
freeStrArr(arr);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
char **
|
||
|
addStrArr(char **arr, const char *str, int len)
|
||
|
{
|
||
|
char **strp;
|
||
|
|
||
|
if ((arr = extStrArr(arr, &strp))) {
|
||
|
if (strNDup(strp, str, len))
|
||
|
return arr;
|
||
|
freeStrArr(arr);
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
char **
|
||
|
xCopyStrArr(int rn, char **arr)
|
||
|
{
|
||
|
char **rarr;
|
||
|
int nu;
|
||
|
|
||
|
nu = arrLen(arr);
|
||
|
if ((rarr = Calloc(sizeof(char *), nu + rn + 1)))
|
||
|
memcpy(rarr + rn, arr, sizeof(char *) * nu);
|
||
|
return rarr;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
freeStrArr(char **arr)
|
||
|
{
|
||
|
char **a;
|
||
|
|
||
|
if (arr) {
|
||
|
for (a = arr; *a; a++)
|
||
|
free(*a);
|
||
|
free(arr);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
char **
|
||
|
parseArgs(char **argv, const char *string)
|
||
|
{
|
||
|
const char *word;
|
||
|
char **strp, *str;
|
||
|
int wlen;
|
||
|
|
||
|
if (!(argv = initStrArr(argv)))
|
||
|
return 0;
|
||
|
while (*string) {
|
||
|
if (isspace(*string)) {
|
||
|
string++;
|
||
|
continue;
|
||
|
}
|
||
|
word = string;
|
||
|
wlen = 0;
|
||
|
do {
|
||
|
if (*string == '\\') {
|
||
|
if (!*++string)
|
||
|
string--;
|
||
|
wlen++;
|
||
|
} else if (*string == '\'') {
|
||
|
while (*++string != '\'' && *string)
|
||
|
wlen++;
|
||
|
} else if (*string == '"') {
|
||
|
while (*++string != '"' && *string) {
|
||
|
if (*string == '\\') {
|
||
|
if (!*++string)
|
||
|
string--;
|
||
|
}
|
||
|
wlen++;
|
||
|
}
|
||
|
} else {
|
||
|
wlen++;
|
||
|
}
|
||
|
} while (*++string && !isspace(*string));
|
||
|
if (!(argv = extStrArr(argv, &strp)))
|
||
|
return 0;
|
||
|
if (!(*strp = str = Malloc(wlen + 1))) {
|
||
|
freeStrArr(argv);
|
||
|
return 0;
|
||
|
}
|
||
|
do {
|
||
|
if (*word == '\\') {
|
||
|
if (!*++word)
|
||
|
word--;
|
||
|
*str++ = *word;
|
||
|
} else if (*word == '\'') {
|
||
|
while (*++word != '\'' && *word)
|
||
|
*str++ = *word;
|
||
|
} else if (*word == '"') {
|
||
|
while (*++word != '"' && *word) {
|
||
|
if (*word == '\\') {
|
||
|
if (!*++word)
|
||
|
word--;
|
||
|
}
|
||
|
*str++ = *word;
|
||
|
}
|
||
|
} else {
|
||
|
*str++ = *word;
|
||
|
}
|
||
|
} while (*++word && !isspace(*word));
|
||
|
*str = 0;
|
||
|
}
|
||
|
return argv;
|
||
|
}
|
||
|
|
||
|
|
||
|
const char *
|
||
|
getEnv(char **e, const char *name)
|
||
|
{
|
||
|
if (e) {
|
||
|
int l = strlen(name);
|
||
|
for (; *e; e++)
|
||
|
if (!memcmp(*e, name, l) && (*e)[l] == '=')
|
||
|
return (*e) + l + 1;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
char **
|
||
|
setEnv(char **e, const char *name, const char *value)
|
||
|
{
|
||
|
char **new, **old;
|
||
|
char *newe;
|
||
|
int envsize;
|
||
|
int l;
|
||
|
|
||
|
newe = 0;
|
||
|
if (!strApp(&newe, name, "=", value, (char *)0))
|
||
|
return e;
|
||
|
envsize = 0;
|
||
|
if (e) {
|
||
|
l = strlen(name);
|
||
|
for (old = e; *old; old++)
|
||
|
if (!memcmp(*old, name, l) && ((*old)[l] == '=' || !(*old)[l])) {
|
||
|
free(*old);
|
||
|
*old = newe;
|
||
|
return e;
|
||
|
}
|
||
|
envsize = old - e;
|
||
|
}
|
||
|
if (!(new = Realloc(e, (unsigned)((envsize + 2) * sizeof(char *))))) {
|
||
|
free(newe);
|
||
|
return e;
|
||
|
}
|
||
|
new[envsize] = newe;
|
||
|
new[envsize + 1] = 0;
|
||
|
return new;
|
||
|
}
|
||
|
|
||
|
char **
|
||
|
putEnv(const char *string, char **env)
|
||
|
{
|
||
|
char *b, *n;
|
||
|
|
||
|
if (!(b = strchr(string, '=')))
|
||
|
return 0;
|
||
|
if (!strNDup(&n, string, b - string))
|
||
|
return 0;
|
||
|
env = setEnv(env, n, b + 1);
|
||
|
free(n);
|
||
|
return env;
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
getHostname(char *buf, int maxlen)
|
||
|
{
|
||
|
int len;
|
||
|
|
||
|
#ifdef NEED_UTSNAME
|
||
|
/*
|
||
|
* same host name crock as in server and xinit.
|
||
|
*/
|
||
|
struct utsname name;
|
||
|
|
||
|
uname(&name);
|
||
|
len = strlen(name.nodename);
|
||
|
if (len >= maxlen)
|
||
|
len = maxlen - 1;
|
||
|
memcpy(buf, name.nodename, len);
|
||
|
buf[len] = '\0';
|
||
|
#else
|
||
|
buf[0] = '\0';
|
||
|
(void)gethostname(buf, maxlen);
|
||
|
buf[maxlen - 1] = '\0';
|
||
|
len = strlen(buf);
|
||
|
#endif /* NEED_UTSNAME */
|
||
|
return len;
|
||
|
}
|
||
|
|
||
|
static char localHostbuf[256];
|
||
|
static int gotLocalHostname;
|
||
|
|
||
|
const char *
|
||
|
localHostname(void)
|
||
|
{
|
||
|
if (!gotLocalHostname) {
|
||
|
getHostname(localHostbuf, sizeof(localHostbuf) - 1);
|
||
|
gotLocalHostname = True;
|
||
|
}
|
||
|
return localHostbuf;
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
atomicIO(ssize_t (*f)(int, void *, size_t), int fd, void *buf, int count)
|
||
|
{
|
||
|
int ret, rlen;
|
||
|
|
||
|
for (rlen = 0; rlen < count;) {
|
||
|
dord:
|
||
|
ret = f(fd, (char *)buf + rlen, count - rlen);
|
||
|
if (ret < 0) {
|
||
|
if (errno == EINTR)
|
||
|
goto dord;
|
||
|
if (errno == EAGAIN)
|
||
|
break;
|
||
|
return -1;
|
||
|
}
|
||
|
if (!ret)
|
||
|
break;
|
||
|
rlen += ret;
|
||
|
}
|
||
|
return rlen;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
reader(int fd, void *buf, int count)
|
||
|
{
|
||
|
return atomicIO(read, fd, buf, count);
|
||
|
}
|
||
|
|
||
|
int
|
||
|
writer(int fd, const void *buf, int count)
|
||
|
{
|
||
|
return atomicIO((ssize_t(*)(int, void *, size_t))write,
|
||
|
fd, (void *)buf, count);
|
||
|
}
|
||
|
|
||
|
int
|
||
|
fGets(char *buf, int max, FILE *f)
|
||
|
{
|
||
|
int len;
|
||
|
|
||
|
if (!fgets(buf, max, f))
|
||
|
return -1;
|
||
|
len = strlen(buf);
|
||
|
if (len && buf[len - 1] == '\n')
|
||
|
buf[--len] = 0;
|
||
|
return len;
|
||
|
}
|
||
|
|
||
|
time_t
|
||
|
mTime(const char *fn)
|
||
|
{
|
||
|
struct stat st;
|
||
|
|
||
|
if (stat(fn, &st))
|
||
|
return -1;
|
||
|
else
|
||
|
return st.st_mtime;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
randomStr(char *s)
|
||
|
{
|
||
|
static const char letters[] =
|
||
|
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||
|
unsigned i, rn = secureRandom();
|
||
|
|
||
|
for (i = 0; i < 6; i++) {
|
||
|
*s++ = letters[rn % 62];
|
||
|
rn /= 62;
|
||
|
}
|
||
|
*s = 0;
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
strNChrCnt(const char *s, int slen, char c)
|
||
|
{
|
||
|
int i, cnt;
|
||
|
|
||
|
for (i = cnt = 0; i < slen && s[i]; i++)
|
||
|
if (s[i] == c)
|
||
|
cnt++;
|
||
|
return cnt;
|
||
|
}
|
||
|
|
||
|
#define atox(c) ('0' <= c && c <= '9' ? c - '0' : \
|
||
|
'a' <= c && c <= 'f' ? c - 'a' + 10 : \
|
||
|
'A' <= c && c <= 'F' ? c - 'A' + 10 : -1)
|
||
|
|
||
|
int
|
||
|
hexToBinary(char *out, const char *in)
|
||
|
{
|
||
|
int top, bottom;
|
||
|
char c;
|
||
|
char *oout;
|
||
|
|
||
|
for (oout = out; (c = *in++);) {
|
||
|
if ((top = atox(c)) < 0)
|
||
|
return 0;
|
||
|
if (!(c = *in++))
|
||
|
return 0;
|
||
|
if ((bottom = atox(c)) < 0)
|
||
|
return 0;
|
||
|
*out++ = (top << 4) | bottom;
|
||
|
}
|
||
|
return out - oout;
|
||
|
}
|
||
|
|
||
|
#undef atox
|
||
|
|
||
|
/* X -from ip6-addr does not work here, so i don't know whether this is needed.
|
||
|
#define IP6_MAGIC
|
||
|
*/
|
||
|
|
||
|
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
|
||
|
)
|
||
|
{
|
||
|
if (ut->ut_pid <= 0 || (kill(ut->ut_pid, 0) < 0 && errno == ESRCH))
|
||
|
continue; /* ignore stale utmp entries */
|
||
|
#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
|
||
|
endpwent(); /* The TTY callbacks use getpwnam(). */
|
||
|
}
|
||
|
|
||
|
typedef struct {
|
||
|
int any;
|
||
|
int uid;
|
||
|
} AULData;
|
||
|
|
||
|
static void
|
||
|
noteXSession(struct display *di, struct display *d, void *ctx)
|
||
|
{
|
||
|
AULData *dt = (AULData *)ctx;
|
||
|
(void)d;
|
||
|
|
||
|
if (di->status == remoteLogin || di->userSess != dt->uid)
|
||
|
dt->any = True;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
noteTTYSession(STRUCTUTMP *ut, struct display *d, void *ctx)
|
||
|
{
|
||
|
AULData *dt = (AULData *)ctx;
|
||
|
struct passwd *pw;
|
||
|
(void)d;
|
||
|
|
||
|
if (dt->uid < 0 || !(pw = getpwnam(ut->ut_user)) || (int)pw->pw_uid != dt->uid)
|
||
|
dt->any = True;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
anyUserLogins(int uid)
|
||
|
{
|
||
|
AULData dt;
|
||
|
|
||
|
dt.any = False;
|
||
|
dt.uid = uid;
|
||
|
listSessions(lstRemote | lstTTY, 0, &dt, noteXSession, noteTTYSession);
|
||
|
return dt.any;
|
||
|
}
|
||
|
|