diff options
Diffstat (limited to 'kdm/backend/util.c')
-rw-r--r-- | kdm/backend/util.c | 621 |
1 files changed, 621 insertions, 0 deletions
diff --git a/kdm/backend/util.c b/kdm/backend/util.c new file mode 100644 index 000000000..a5358cd65 --- /dev/null +++ b/kdm/backend/util.c @@ -0,0 +1,621 @@ +/* + +Copyright 1989, 1998 The Open Group +Copyright 2000-2005 Oswald Buddenhagen <[email protected]> + +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_error.h" + +#include <string.h> +#include <unistd.h> +#include <ctype.h> +#include <sys/types.h> +#include <sys/stat.h> + +#if 0 /*def USG; this was hpux once upon a time */ +# define NEED_UTSNAME +#endif + +#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; +} + +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 0; + memcpy( *dst, src, len ); + (*dst)[len] = 0; + } else + *dst = 0; + return 1; +} + +int +StrDup( char **dst, const char *src ) +{ + return StrNDup( dst, src, -1 ); +} + +/* 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 ))) { + if (*dst) { + free( *dst ); + *dst = 0; + } + return 0; + } + 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 1; +} + + +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; +} + +static 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; + +#ifdef _AIX + /* setpenv() depends on "SYSENVIRON:", not "SYSENVIRON:=" */ + if (!value) { + if (!StrDup( &newe, name )) + return e; + } else +#endif + { + 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 = (char **) + Realloc( (char *)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 NULL; + if (!StrNDup( &n, string, b - string )) + return NULL; + 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 = 1; + } + 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, (void *)((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; +} + +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; +} + +/* 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 + ) + { +#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 +} + |