add more spacing
[personal-kdebase.git] / workspace / kdm / backend / util.c
blobeff69aab9e5c206f5dd8d8dd3a19fddaa8de9de2
1 /*
3 Copyright 1989, 1998 The Open Group
4 Copyright 2000-2005 Oswald Buddenhagen <ossi@kde.org>
6 Permission to use, copy, modify, distribute, and sell this software and its
7 documentation for any purpose is hereby granted without fee, provided that
8 the above copyright notice appear in all copies and that both that
9 copyright notice and this permission notice appear in supporting
10 documentation.
12 The above copyright notice and this permission notice shall be included
13 in all copies or substantial portions of the Software.
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21 OTHER DEALINGS IN THE SOFTWARE.
23 Except as contained in this notice, the name of a copyright holder shall
24 not be used in advertising or otherwise to promote the sale, use or
25 other dealings in this Software without prior written authorization
26 from the copyright holder.
31 * xdm - display manager daemon
32 * Author: Keith Packard, MIT X Consortium
34 * various utility routines
37 #include "dm.h"
38 #include "dm_error.h"
40 #include <string.h>
41 #include <unistd.h>
42 #include <pwd.h>
43 #include <ctype.h>
44 #include <sys/types.h>
45 #include <sys/stat.h>
47 #if 0 /*def USG; this was hpux once upon a time */
48 # define NEED_UTSNAME
49 #endif
51 #ifdef NEED_UTSNAME
52 # include <sys/utsname.h>
53 #endif
55 void *
56 Calloc( size_t nmemb, size_t size )
58 void *ret;
60 if (!(ret = calloc( nmemb, size )))
61 logOutOfMem();
62 return ret;
65 void *
66 Malloc( size_t size )
68 void *ret;
70 if (!(ret = malloc( size )))
71 logOutOfMem();
72 return ret;
75 void *
76 Realloc( void *ptr, size_t size )
78 void *ret;
80 if (!(ret = realloc( ptr, size )) && size)
81 logOutOfMem();
82 return ret;
85 int
86 strCmp( const char *s1, const char *s2 )
88 if (s1 == s2)
89 return 0;
90 if (!s1)
91 return -1;
92 if (!s2)
93 return 1;
94 return strcmp( s1, s2 );
97 void
98 wipeStr( char *str )
100 if (str) {
101 bzero( str, strlen( str ) );
102 free( str );
106 #ifndef HAVE_STRNLEN
108 strnlen( const char *s, int max )
110 unsigned l;
112 for (l = 0; l < (unsigned)max && s[l]; l++);
113 return l;
115 #endif
117 /* duplicate src; wipe & free old dst string */
119 reStrN( char **dst, const char *src, int len )
121 char *ndst = 0;
123 if (src) {
124 if (len < 0)
125 len = strlen( src );
126 if (*dst && !memcmp( *dst, src, len ) && !(*dst)[len])
127 return 1;
128 if (!(ndst = Malloc( len + 1 ))) {
129 wipeStr( *dst );
130 *dst = 0;
131 return 0;
133 memcpy( ndst, src, len );
134 ndst[len] = 0;
136 wipeStr( *dst ); /* make an option, if we should become heavily used */
137 *dst = ndst;
138 return 2;
142 reStr( char **dst, const char *src )
144 return reStrN( dst, src, -1 );
147 /* duplicate src */
149 strNDup( char **dst, const char *src, int len )
151 if (src) {
152 if (len < 0)
153 len = strlen( src );
154 if (!(*dst = Malloc( len + 1 )))
155 return False;
156 memcpy( *dst, src, len );
157 (*dst)[len] = 0;
158 } else
159 *dst = 0;
160 return True;
164 strDup( char **dst, const char *src )
166 return strNDup( dst, src, -1 );
169 /* append any number of strings to dst */
171 strApp( char **dst, ... )
173 int len;
174 char *bk, *pt, *dp;
175 va_list va;
177 len = 1;
178 if (*dst)
179 len += strlen( *dst );
180 va_start( va, dst );
181 for (;;) {
182 pt = va_arg( va, char * );
183 if (!pt)
184 break;
185 len += strlen( pt );
187 va_end( va );
188 if (!(bk = Malloc( len ))) {
189 if (*dst) {
190 free( *dst );
191 *dst = 0;
193 return False;
195 dp = bk;
196 if (*dst) {
197 len = strlen( *dst );
198 memcpy( dp, *dst, len );
199 dp += len;
200 free( *dst );
202 va_start( va, dst );
203 for (;;) {
204 pt = va_arg( va, char * );
205 if (!pt)
206 break;
207 len = strlen( pt );
208 memcpy( dp, pt, len );
209 dp += len;
211 va_end( va );
212 *dp = '\0';
213 *dst = bk;
214 return True;
217 char *
218 expandMacros( const char *str, struct expando *expandos )
220 struct expando *ex;
221 int cnt = 0, rcnt, vl;
222 const char *sp = str;
223 char *ret, *cp;
224 char c;
226 oke1:
227 while ((c = *sp++)) {
228 if (c == '%') {
229 rcnt = 0;
230 for (;;) {
231 c = *sp++;
232 if (!c)
233 goto murks1;
234 if (c == '%')
235 break;
236 for (ex = expandos; ex->key; ex++)
237 if (c == ex->key) {
238 if (ex->val)
239 cnt += strlen( ex->val ) + rcnt;
240 goto oke1;
242 rcnt++;
245 cnt++;
247 murks1:
248 if (!(cp = ret = Malloc( cnt + 1 )))
249 return 0;
250 oke2:
251 while ((c = *str++)) {
252 if (c == '%') {
253 rcnt = 0;
254 for (;;) {
255 c = *str++;
256 if (!c)
257 goto murks2;
258 if (c == '%')
259 break;
260 for (ex = expandos; ex->key; ex++)
261 if (c == ex->key) {
262 if (ex->val) {
263 vl = strlen( ex->val );
264 memcpy( cp, str - 1 - rcnt, rcnt );
265 memcpy( cp + rcnt, ex->val, vl );
266 cp += vl + rcnt;
268 ex->uses++;
269 goto oke2;
271 rcnt++;
274 *cp++ = c;
276 murks2:
277 *cp = 0;
278 return ret;
282 char **
283 initStrArr( char **arr )
285 if (!arr && (arr = Malloc( sizeof(char *) )))
286 arr[0] = 0;
287 return arr;
291 arrLen( char **arr )
293 int nu = 0;
294 if (arr)
295 for (; arr[nu]; nu++);
296 return nu;
299 static char **
300 extStrArr( char **arr, char ***strp )
302 char **rarr;
303 int nu;
305 nu = arrLen( arr );
306 if ((rarr = Realloc( arr, sizeof(char *) * (nu + 2) ))) {
307 rarr[nu + 1] = 0;
308 *strp = rarr + nu;
309 return rarr;
311 freeStrArr( arr );
312 return 0;
315 char **
316 addStrArr( char **arr, const char *str, int len )
318 char **strp;
320 if ((arr = extStrArr( arr, &strp ))) {
321 if (strNDup( strp, str, len ))
322 return arr;
323 freeStrArr( arr );
325 return 0;
328 char **
329 xCopyStrArr( int rn, char **arr )
331 char **rarr;
332 int nu;
334 nu = arrLen( arr );
335 if ((rarr = Calloc( sizeof(char *), nu + rn + 1 )))
336 memcpy( rarr + rn, arr, sizeof(char *) * nu );
337 return rarr;
340 void
341 freeStrArr( char **arr )
343 char **a;
345 if (arr) {
346 for (a = arr; *a; a++)
347 free( *a );
348 free( arr );
353 char **
354 parseArgs( char **argv, const char *string )
356 const char *word;
357 char **strp, *str;
358 int wlen;
360 if (!(argv = initStrArr( argv )))
361 return 0;
362 while (*string) {
363 if (isspace( *string )) {
364 string++;
365 continue;
367 word = string;
368 wlen = 0;
369 do {
370 if (*string == '\\') {
371 if (!*++string)
372 string--;
373 wlen++;
374 } else if (*string == '\'') {
375 while (*++string != '\'' && *string)
376 wlen++;
377 } else if (*string == '"') {
378 while (*++string != '"' && *string) {
379 if (*string == '\\') {
380 if (!*++string)
381 string--;
383 wlen++;
385 } else
386 wlen++;
387 } while (*++string && !isspace( *string ));
388 if (!(argv = extStrArr( argv, &strp )))
389 return 0;
390 if (!(*strp = str = Malloc( wlen + 1 ))) {
391 freeStrArr( argv );
392 return 0;
394 do {
395 if (*word == '\\') {
396 if (!*++word)
397 word--;
398 *str++ = *word;
399 } else if (*word == '\'') {
400 while (*++word != '\'' && *word)
401 *str++ = *word;
402 } else if (*word == '"') {
403 while (*++word != '"' && *word) {
404 if (*word == '\\') {
405 if (!*++word)
406 word--;
408 *str++ = *word;
410 } else
411 *str++ = *word;
412 } while (*++word && !isspace( *word ));
413 *str = 0;
415 return argv;
419 const char *
420 getEnv( char **e, const char *name )
422 if (e) {
423 int l = strlen( name );
424 for (; *e; e++)
425 if (!memcmp( *e, name, l ) && (*e)[l] == '=')
426 return (*e) + l + 1;
428 return 0;
431 char **
432 setEnv( char **e, const char *name, const char *value )
434 char **new, **old;
435 char *newe;
436 int envsize;
437 int l;
439 newe = 0;
440 if (!strApp( &newe, name, "=", value, (char *)0 ))
441 return e;
442 envsize = 0;
443 if (e) {
444 l = strlen( name );
445 for (old = e; *old; old++)
446 if (!memcmp( *old, name, l ) && ((*old)[l] == '=' || !(*old)[l]))
448 free( *old );
449 *old = newe;
450 return e;
452 envsize = old - e;
454 if (!(new = (char **)
455 Realloc( (char *)e, (unsigned)((envsize + 2) * sizeof(char *)) )))
457 free( newe );
458 return e;
460 new[envsize] = newe;
461 new[envsize + 1] = 0;
462 return new;
465 char **
466 putEnv( const char *string, char **env )
468 char *b, *n;
470 if (!(b = strchr( string, '=' )))
471 return NULL;
472 if (!strNDup( &n, string, b - string ))
473 return NULL;
474 env = setEnv( env, n, b + 1 );
475 free( n );
476 return env;
479 static int
480 getHostname( char *buf, int maxlen )
482 int len;
484 #ifdef NEED_UTSNAME
486 * same host name crock as in server and xinit.
488 struct utsname name;
490 uname( &name );
491 len = strlen( name.nodename );
492 if (len >= maxlen) len = maxlen - 1;
493 memcpy( buf, name.nodename, len );
494 buf[len] = '\0';
495 #else
496 buf[0] = '\0';
497 (void)gethostname( buf, maxlen );
498 buf[maxlen - 1] = '\0';
499 len = strlen( buf );
500 #endif /* NEED_UTSNAME */
501 return len;
504 static char localHostbuf[256];
505 static int gotLocalHostname;
507 const char *
508 localHostname( void )
510 if (!gotLocalHostname)
512 getHostname( localHostbuf, sizeof(localHostbuf) - 1 );
513 gotLocalHostname = True;
515 return localHostbuf;
518 static int
519 atomicIO( ssize_t (*f)( int, void *, size_t ), int fd, void *buf, int count )
521 int ret, rlen;
523 for (rlen = 0; rlen < count; ) {
524 dord:
525 ret = f( fd, (void *)((char *)buf + rlen), count - rlen );
526 if (ret < 0) {
527 if (errno == EINTR)
528 goto dord;
529 if (errno == EAGAIN)
530 break;
531 return -1;
533 if (!ret)
534 break;
535 rlen += ret;
537 return rlen;
541 reader( int fd, void *buf, int count )
543 return atomicIO( read, fd, buf, count );
547 writer( int fd, const void *buf, int count )
549 return atomicIO( (ssize_t(*)( int, void *, size_t ))write,
550 fd, (void *)buf, count );
554 fGets( char *buf, int max, FILE *f )
556 int len;
558 if (!fgets( buf, max, f ))
559 return -1;
560 len = strlen( buf );
561 if (len && buf[len - 1] == '\n')
562 buf[--len] = 0;
563 return len;
566 time_t
567 mTime( const char *fn )
569 struct stat st;
571 if (stat( fn, &st ))
572 return -1;
573 else
574 return st.st_mtime;
577 static int
578 strNChrCnt( const char *s, int slen, char c )
580 int i, cnt;
582 for (i = cnt = 0; i < slen && s[i]; i++)
583 if (s[i] == c)
584 cnt++;
585 return cnt;
588 /* X -from ip6-addr does not work here, so i don't know whether this is needed.
589 #define IP6_MAGIC
592 void
593 listSessions( int flags, struct display *d, void *ctx,
594 void (*emitXSess)( struct display *, struct display *, void * ),
595 void (*emitTTYSess)( STRUCTUTMP *, struct display *, void * ) )
597 struct display *di;
598 #ifdef IP6_MAGIC
599 int le, dot;
600 #endif
601 #ifdef BSD_UTMP
602 int fd;
603 struct utmp ut[1];
604 #else
605 STRUCTUTMP *ut;
606 #endif
608 for (di = displays; di; di = di->next)
609 if (((flags & lstRemote) || (di->displayType & d_location) == dLocal) &&
610 (di->status == remoteLogin ||
611 ((flags & lstPassive) ? di->status == running : di->userSess >= 0)))
612 emitXSess( di, d, ctx );
614 if (!(flags & lstTTY))
615 return;
617 #ifdef BSD_UTMP
618 if ((fd = open( UTMP_FILE, O_RDONLY )) < 0)
619 return;
620 while (reader( fd, ut, sizeof(ut[0]) ) == sizeof(ut[0])) {
621 if (*ut->ut_user) { /* no idea how to list passive TTYs on BSD */
622 #else
623 SETUTENT();
624 while ((ut = GETUTENT())) {
625 if (ut->ut_type == USER_PROCESS
626 # if 0 /* list passive TTYs at all? not too sensible, i think. */
627 || ((flags & lstPassive) && ut->ut_type == LOGIN_PROCESS)
628 # endif
631 #endif
632 if (*ut->ut_host) { /* from remote or x */
633 if (!(flags & lstRemote))
634 continue;
635 } else {
636 /* hack around broken konsole which does not set ut_host. */
637 /* this check is probably linux-specific. */
638 /* alternatively we could open the device and try VT_OPENQRY. */
639 if (memcmp( ut->ut_line, "tty", 3 ) ||
640 !isdigit( ut->ut_line[3] ))
641 continue;
643 if (strNChrCnt( ut->ut_line, sizeof(ut->ut_line), ':' ))
644 continue; /* x login */
645 switch (strNChrCnt( ut->ut_host, sizeof(ut->ut_host), ':' )) {
646 case 1: /* x terminal */
647 continue;
648 default:
649 #ifdef IP6_MAGIC
650 /* unknown - IPv6 makes things complicated */
651 le = strnlen( ut->ut_host, sizeof(ut->ut_host) );
652 /* cut off screen number */
653 for (dot = le; ut->ut_host[--dot] != ':'; )
654 if (ut->ut_host[dot] == '.') {
655 le = dot;
656 break;
658 for (di = displays; di; di = di->next)
659 if (!memcmp( di->name, ut->ut_host, le ) && !di->name[le])
660 goto cont; /* x terminal */
661 break;
662 cont:
663 continue;
664 case 0: /* no x terminal */
665 #endif
666 break;
668 emitTTYSess( ut, d, ctx );
671 #ifdef BSD_UTMP
672 close( fd );
673 #else
674 ENDUTENT();
675 #endif
676 endpwent(); /* The TTY callbacks use getpwnam(). */
679 typedef struct {
680 int any;
681 int uid;
682 } AULData;
684 static void
685 noteXSession( struct display *di, struct display *d, void *ctx )
687 AULData *dt = (AULData *)ctx;
688 (void)d;
690 if (di->status == remoteLogin || di->userSess != dt->uid)
691 dt->any = True;
694 static void
695 noteTTYSession( STRUCTUTMP *ut, struct display *d, void *ctx )
697 AULData *dt = (AULData *)ctx;
698 struct passwd *pw;
699 (void)d;
701 if (dt->uid < 0 ||
702 !(pw = getpwnam( ut->ut_user )) || (int)pw->pw_uid != dt->uid)
703 dt->any = True;
707 anyUserLogins( int uid )
709 AULData dt;
711 dt.any = False;
712 dt.uid = uid;
713 listSessions( lstRemote | lstTTY, 0, &dt, noteXSession, noteTTYSession );
714 return dt.any;