summaryrefslogtreecommitdiffstats
path: root/kdm/backend/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'kdm/backend/util.c')
-rw-r--r--kdm/backend/util.c621
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
+}
+