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
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
44 #include <sys/types.h>
47 #if 0 /*def USG; this was hpux once upon a time */
52 # include <sys/utsname.h>
56 Calloc( size_t nmemb
, size_t size
)
60 if (!(ret
= calloc( nmemb
, size
)))
70 if (!(ret
= malloc( size
)))
76 Realloc( void *ptr
, size_t size
)
80 if (!(ret
= realloc( ptr
, size
)) && size
)
86 strCmp( const char *s1
, const char *s2
)
94 return strcmp( s1
, s2
);
101 bzero( str
, strlen( str
) );
108 strnlen( const char *s
, int max
)
112 for (l
= 0; l
< (unsigned)max
&& s
[l
]; l
++);
117 /* duplicate src; wipe & free old dst string */
119 reStrN( char **dst
, const char *src
, int len
)
126 if (*dst
&& !memcmp( *dst
, src
, len
) && !(*dst
)[len
])
128 if (!(ndst
= Malloc( len
+ 1 ))) {
133 memcpy( ndst
, src
, len
);
136 wipeStr( *dst
); /* make an option, if we should become heavily used */
142 reStr( char **dst
, const char *src
)
144 return reStrN( dst
, src
, -1 );
149 strNDup( char **dst
, const char *src
, int len
)
154 if (!(*dst
= Malloc( len
+ 1 )))
156 memcpy( *dst
, src
, len
);
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
, ... )
179 len
+= strlen( *dst
);
182 pt
= va_arg( va
, char * );
188 if (!(bk
= Malloc( len
))) {
197 len
= strlen( *dst
);
198 memcpy( dp
, *dst
, len
);
204 pt
= va_arg( va
, char * );
208 memcpy( dp
, pt
, len
);
218 expandMacros( const char *str
, struct expando
*expandos
)
221 int cnt
= 0, rcnt
, vl
;
222 const char *sp
= str
;
227 while ((c
= *sp
++)) {
236 for (ex
= expandos
; ex
->key
; ex
++)
239 cnt
+= strlen( ex
->val
) + rcnt
;
248 if (!(cp
= ret
= Malloc( cnt
+ 1 )))
251 while ((c
= *str
++)) {
260 for (ex
= expandos
; ex
->key
; ex
++)
263 vl
= strlen( ex
->val
);
264 memcpy( cp
, str
- 1 - rcnt
, rcnt
);
265 memcpy( cp
+ rcnt
, ex
->val
, vl
);
283 initStrArr( char **arr
)
285 if (!arr
&& (arr
= Malloc( sizeof(char *) )))
295 for (; arr
[nu
]; nu
++);
300 extStrArr( char **arr
, char ***strp
)
306 if ((rarr
= Realloc( arr
, sizeof(char *) * (nu
+ 2) ))) {
316 addStrArr( char **arr
, const char *str
, int len
)
320 if ((arr
= extStrArr( arr
, &strp
))) {
321 if (strNDup( strp
, str
, len
))
329 xCopyStrArr( int rn
, char **arr
)
335 if ((rarr
= Calloc( sizeof(char *), nu
+ rn
+ 1 )))
336 memcpy( rarr
+ rn
, arr
, sizeof(char *) * nu
);
341 freeStrArr( char **arr
)
346 for (a
= arr
; *a
; a
++)
354 parseArgs( char **argv
, const char *string
)
360 if (!(argv
= initStrArr( argv
)))
363 if (isspace( *string
)) {
370 if (*string
== '\\') {
374 } else if (*string
== '\'') {
375 while (*++string
!= '\'' && *string
)
377 } else if (*string
== '"') {
378 while (*++string
!= '"' && *string
) {
379 if (*string
== '\\') {
387 } while (*++string
&& !isspace( *string
));
388 if (!(argv
= extStrArr( argv
, &strp
)))
390 if (!(*strp
= str
= Malloc( wlen
+ 1 ))) {
399 } else if (*word
== '\'') {
400 while (*++word
!= '\'' && *word
)
402 } else if (*word
== '"') {
403 while (*++word
!= '"' && *word
) {
412 } while (*++word
&& !isspace( *word
));
420 getEnv( char **e
, const char *name
)
423 int l
= strlen( name
);
425 if (!memcmp( *e
, name
, l
) && (*e
)[l
] == '=')
432 setEnv( char **e
, const char *name
, const char *value
)
440 if (!strApp( &newe
, name
, "=", value
, (char *)0 ))
445 for (old
= e
; *old
; old
++)
446 if (!memcmp( *old
, name
, l
) && ((*old
)[l
] == '=' || !(*old
)[l
]))
454 if (!(new = (char **)
455 Realloc( (char *)e
, (unsigned)((envsize
+ 2) * sizeof(char *)) )))
461 new[envsize
+ 1] = 0;
466 putEnv( const char *string
, char **env
)
470 if (!(b
= strchr( string
, '=' )))
472 if (!strNDup( &n
, string
, b
- string
))
474 env
= setEnv( env
, n
, b
+ 1 );
480 getHostname( char *buf
, int maxlen
)
486 * same host name crock as in server and xinit.
491 len
= strlen( name
.nodename
);
492 if (len
>= maxlen
) len
= maxlen
- 1;
493 memcpy( buf
, name
.nodename
, len
);
497 (void)gethostname( buf
, maxlen
);
498 buf
[maxlen
- 1] = '\0';
500 #endif /* NEED_UTSNAME */
504 static char localHostbuf
[256];
505 static int gotLocalHostname
;
508 localHostname( void )
510 if (!gotLocalHostname
)
512 getHostname( localHostbuf
, sizeof(localHostbuf
) - 1 );
513 gotLocalHostname
= True
;
519 atomicIO( ssize_t (*f
)( int, void *, size_t ), int fd
, void *buf
, int count
)
523 for (rlen
= 0; rlen
< count
; ) {
525 ret
= f( fd
, (void *)((char *)buf
+ rlen
), count
- 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
)
558 if (!fgets( buf
, max
, f
))
561 if (len
&& buf
[len
- 1] == '\n')
567 mTime( const char *fn
)
578 strNChrCnt( const char *s
, int slen
, char c
)
582 for (i
= cnt
= 0; i
< slen
&& s
[i
]; i
++)
588 /* X -from ip6-addr does not work here, so i don't know whether this is needed.
593 listSessions( int flags
, struct display
*d
, void *ctx
,
594 void (*emitXSess
)( struct display
*, struct display
*, void * ),
595 void (*emitTTYSess
)( STRUCTUTMP
*, struct display
*, void * ) )
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
))
618 if ((fd
= open( UTMP_FILE
, O_RDONLY
)) < 0)
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 */
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
)
632 if (*ut
->ut_host
) { /* from remote or x */
633 if (!(flags
& lstRemote
))
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] ))
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 */
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
] == '.') {
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 */
664 case 0: /* no x terminal */
668 emitTTYSess( ut
, d
, ctx
);
676 endpwent(); /* The TTY callbacks use getpwnam(). */
685 noteXSession( struct display
*di
, struct display
*d
, void *ctx
)
687 AULData
*dt
= (AULData
*)ctx
;
690 if (di
->status
== remoteLogin
|| di
->userSess
!= dt
->uid
)
695 noteTTYSession( STRUCTUTMP
*ut
, struct display
*d
, void *ctx
)
697 AULData
*dt
= (AULData
*)ctx
;
702 !(pw
= getpwnam( ut
->ut_user
)) || (int)pw
->pw_uid
!= dt
->uid
)
707 anyUserLogins( int uid
)
713 listSessions( lstRemote
| lstTTY
, 0, &dt
, noteXSession
, noteTTYSession
);