3
Copyright 1988, 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
* global xdm core declarations
42
#define WANT_CORE_DECLS
45
#include <X11/X.h> /* FamilyInternet6 */
47
#include <X11/Xfuncs.h>
49
#include <X11/Xauth.h>
51
#include <sys/param.h>
61
extern char **environ;
65
/* someone somewhere defines QUERY under Tru64 which confuses Xdmcp.h */
68
# include <X11/Xdmcp.h>
73
# define PATH_MAX MAXPATHLEN
75
# define PATH_MAX 1024
80
#define waitCode(w) (WIFEXITED(w) ? WEXITSTATUS(w) : 0)
81
#define waitSig(w) (WIFSIGNALED(w) ? WTERMSIG(w) : 0)
83
# define waitCore(w) (WCOREDUMP(w))
85
# define waitCore(w) 0 /* not in POSIX. so what? */
88
#define wcCompose(sig,core,code) ((sig) * 256 + (core) * 128 + (code))
89
#define wcFromWait(w) wcCompose(waitSig(w), waitCore(w), waitCode(w))
90
#define wcCode(w) ((w) & 0x7f)
91
#define wcCore(w) (((w) >> 7) & 1)
92
#define wcSig(w) (((w) >> 8) & 0xff)
95
#if defined(__EMX__) || (defined(__NetBSD__) && defined(__sparc__)) /* XXX netbsd? */
96
# define Setjmp(e) setjmp(e)
97
# define Longjmp(e,v) longjmp(e,v)
98
# define Jmp_buf jmp_buf
100
# define Setjmp(e) sigsetjmp(e,1)
101
# define Longjmp(e,v) siglongjmp(e,v)
102
# define Jmp_buf sigjmp_buf
107
# define STRUCTUTMP struct utmpx
108
# define UTMPNAME utmpxname
109
# define SETUTENT setutxent
110
# define GETUTENT getutxent
111
# define PUTUTLINE pututxline
112
# define ENDUTENT endutxent
113
# define ut_time ut_tv.tv_sec
116
# define STRUCTUTMP struct utmp
117
# define UTMPNAME utmpname
118
# define SETUTENT setutent
119
# define GETUTENT getutent
120
# define PUTUTLINE pututline
121
# define ENDUTENT endutent
122
# ifndef HAVE_STRUCT_UTMP_UT_USER
123
# define ut_user ut_name
128
# define WTMP_FILE _PATH_WTMPX
129
# elif defined(_PATH_WTMP)
130
# define WTMP_FILE _PATH_WTMP
132
# define WTMP_FILE "/usr/adm/wtmp"
137
# define UTMP_FILE _PATH_UTMPX
138
# elif defined(_PATH_UTMP)
139
# define UTMP_FILE _PATH_UTMP
141
# define UTMP_FILE "/etc/utmp"
145
#ifdef HAVE_NETCONFIG_H
150
# ifdef FamilyInternet6
153
# ifdef HAVE_NETDNET_DN_H
158
#if !defined(HAVE_ARC4RANDOM) && !defined(DEV_RANDOM)
159
# define NEED_ENTROPY
162
typedef struct GPipe {
163
#if defined(__FreeBSD__) || defined(UNIXCONN)
175
typedef struct GTalk {
180
typedef struct GProc {
185
typedef enum displayStatus {
186
notRunning = 0, /* waiting for being started */
187
running, /* was started */
188
zombie, /* manager and server killed, remove/suspend when both are gone */
189
phoenix, /* server killed, restart when it dies */
190
raiser, /* manager killed, restart when it dies */
191
textMode, /* suspended, console mode */
192
reserve, /* suspended, reserve display */
193
remoteLogin /* running X -query */
196
typedef enum serverStatus {
197
ignore = 0, /* error in this state is no error */
198
awaiting, /* waking for being started */
199
starting, /* process launched, wait max serverTimeout secs */
200
terminated, /* process SIGTERMed, wait max serverTimeout secs */
201
killed, /* process SIGKILLed, wait max 10 secs */
202
pausing /* startup failed, wait openDelay secs */
206
unsigned how:2, /* 0=none 1=reboot 2=halt (SHUT_*) */
216
typedef struct RcStr {
222
typedef struct CfgDep {
227
typedef struct CfgArr {
228
void *data; /* config value array; allocated */
229
int *idx; /* config index array; alias */
230
CfgDep dep; /* filestamp */
231
int numCfgEnt; /* number of config entries */
241
struct cmdsock *next;
242
struct bsock sock; /* buffered fd of the socket */
246
struct cmdsock *css; /* open connections */
248
char *path; /* filename of the socket */
249
#ifndef HONORS_SOCKET_PERMS
250
char *realdir; /* real dirname of the socket */
252
int fd; /* fd of the socket */
253
int gid; /* owner group of the socket */
257
struct display *next;
258
struct disphist *hstent; /* display history entry */
260
/* basic display information */
261
char *name; /* DISPLAY name -- also referenced in hstent */
262
char *class2; /* display class (may be 0) */
263
int displayType; /* location/origin/lifetime */
264
CfgArr cfg; /* config data array */
267
DisplayStatus status; /* current status */
268
int zstatus; /* substatus while zombie */
269
int pid; /* process id of child */
270
int serverPid; /* process id of server (-1 if none) */
272
int serverVT; /* server VT (0 = none, -1 = pending) */
273
struct display *follower; /* on exit, hand VT to this display */
275
ServerStatus serverStatus; /* X server startup state */
276
time_t lastStart; /* time of last display start */
277
int startTries; /* current start try */
278
int stillThere; /* state during HUP processing */
279
int userSess; /* -1=nobody, otherwise uid */
282
SdRec sdRec; /* user session requested shutdown */
283
CtrlRec ctrl; /* command socket */
284
GPipe pipe; /* comm master <-> slave */
285
GPipe gpipe; /* comm master <-> greeter */
287
char *remoteHost; /* for X -query type remote login */
289
unsigned sessionID; /* ID of active session */
290
ARRAY8 peer; /* display peer address (sockaddr) */
291
ARRAY8 from; /* XDMCP peer address (sockaddr) */
292
unsigned displayNumber; /* numerical part of name */
293
int useChooser; /* Run the chooser for this display */
294
ARRAY8 clientAddr; /* for chooser picking */
295
ARRAY8 clientPort; /* ... */
296
unsigned connectionType; /* ... */
302
/* information potentially derived from resources */
303
Xauth **authorizations; /* authorization data */
304
int authNum; /* number of authorizations */
305
char *authFile; /* file to store authorization in */
306
char *greeterAuthFile; /* file to store authorization for greeter in */
310
#define dLocal 1 /* server runs on local host */
311
#define dForeign 0 /* server runs on remote host */
314
#define dPermanent 4 /* display restarted when session exits */
315
#define dReserve 2 /* display not restarted when session exits */
316
#define dTransient 0 /* display removed when session exits */
321
#define d_origin 16 /* clever, huh? :) */
323
#define dFromCommand 16 /* started via command socket */
324
#define dFromXDMCP 8 /* started with XDMCP */
325
#define dFromFile 0 /* started via entry in servers file */
328
struct disphist *next;
330
time_t lastExit; /* time of last display exit */
331
unsigned rLogin:2, /* 0=nothing 1=relogin 2=login */
332
lock:1, /* screen locker running */
333
goodExit:1; /* was the last exit "peaceful"? */
334
char *nuser, *npass, *nargs;
339
#define PROTO_TIMEOUT (30 * 60) /* 30 minutes should be long enough */
341
struct protoDisplay {
342
struct protoDisplay *next;
343
XdmcpNetaddr address; /* UDP address */
344
int addrlen; /* UDP address length */
345
unsigned long date; /* creation date */
346
CARD16 displayNumber;
347
CARD16 connectionType;
348
ARRAY8 connectionAddress;
350
Xauth *fileAuthorization;
351
Xauth *xdmcpAuthorization;
352
ARRAY8 authenticationName;
353
ARRAY8 authenticationData;
358
/* status code for rStopDisplay */
360
# define DS_RESTART 0
361
# define DS_TEXTMODE 1
362
# define DS_RESERVE 2
365
#define DS_SCHEDULE 256 /* flag for DS_TEXTMODE */
367
/* command codes dpy process -> master process */
370
#define D_ChooseHost 4
371
#define D_RemoteHost 5
375
extern int debugLevel;
377
CONF_CORE_GLOBAL_DECLS
380
void becomeDaemon(void);
383
#if KDM_LIBEXEC_STRIP != -1
384
extern char *progpath;
386
#if KDM_LIBEXEC_STRIP
387
extern char *progname;
392
void startDisplayP2(struct display *d);
393
void stopDisplay(struct display *d);
394
#if !defined(HAVE_SETPROCTITLE) && !defined(NOXDMTITLE)
395
void setproctitle(const char *fmt, ...);
397
void wakeDisplays(void);
398
void switchToX(struct display *d);
399
void setNLogin(struct display *d,
400
const char *nuser, const char *npass, const char *nargs,
402
void cancelShutdown(void);
403
int TTYtoVT(const char *tty);
404
int activateVT(int vt);
406
#ifndef _POSIX_MONOTONIC_CLOCK
407
# define _POSIX_MONOTONIC_CLOCK -1
409
#if (_POSIX_MONOTONIC_CLOCK > 0)
410
# define nowMonotonic 1
411
#elif (_POSIX_MONOTONIC_CLOCK < 0)
412
# define nowMonotonic 0
414
extern int nowMonotonic;
416
void updateNow(void);
419
void openCtrl(struct display *d);
420
void closeCtrl(struct display *d);
421
int handleCtrl(fd_set *reads, struct display *d);
422
void chownCtrl(CtrlRec *cr, int uid);
423
void updateCtrl(void);
426
extern struct display *displays; /* that's ugly ... */
427
int anyDisplaysLeft(void);
428
void forEachDisplay(void (*f)(struct display *));
430
void forEachDisplayRev(void (*f)(struct display *));
432
void removeDisplay(struct display *old);
434
*findDisplayByName(const char *name),
436
*findDisplayBySessionID(CARD32 sessionID),
437
*findDisplayByAddress(XdmcpNetaddr addr, int addrlen, CARD16 displayNumber),
439
*findDisplayByPid(int pid),
440
*findDisplayByServerPid(int serverPid),
441
*newDisplay(const char *name);
442
int anyRunningDisplays(void);
443
int anyReserveDisplays(void);
444
int idleReserveDisplays(void);
445
int startReserveDisplay(void);
446
const char *displayName(struct display *);
449
void pseudoReset(void);
452
void **findCfgEnt(struct display *d, int id);
453
int initResources(char **argv);
454
int loadDMResources(int force);
455
int loadDisplayResources(struct display *d);
456
void scanServers(void);
457
void closeGetter(void);
458
int startConfig(int what, CfgDep *dep, int force);
459
RcStr *newStr(char *str);
460
void delStr(RcStr *str);
461
extern GTalk cnftalk;
464
extern struct display *td;
465
extern const char *td_setup;
466
char **baseEnv(char **env, const char *user);
467
char **inheritEnv(char **env, const char **what);
468
char **systemEnv(char **env, const char *user);
469
int source(char **env, const char *file, const char *arg);
470
void manageSession(void);
472
extern GTalk mstrtalk, grttalk;
473
extern GProc grtproc;
474
void openGreeter(void);
475
int closeGreeter(int force);
476
int ctrlGreeterWait(int wreply);
477
void prepareErrorGreet(void);
478
void finishGreet(void);
479
char *conv_interact(int what, const char *prompt);
482
typedef void (*SIGFUNC)(int);
483
SIGFUNC Signal(int, SIGFUNC handler);
485
void registerInput(int fd);
486
void unregisterInput(int fd);
487
void registerCloseOnFork(int fd);
488
void clearCloseOnFork(int fd);
489
void closeNclearCloseOnFork(int fd);
490
int Fork(volatile int *pid);
491
int Wait4(volatile int *pid);
492
void execute(char **argv, char **env);
493
int runAndWait(char **args, char **env);
494
FILE *pOpen(char **what, char m, volatile int *pid);
495
int pClose(FILE *f, volatile int *pid);
496
char *locate(const char *exe);
497
void terminateProcess(int pid, int sig);
498
void blockTerm(void);
499
void unblockTerm(void);
501
void gSet(GTalk *talk); /* call before gOpen! */
502
void gCloseOnExec(GPipe *pajp);
503
int gFork(GPipe *pajp, const char *pname, char *cname,
504
GPipe *ogp, char *cgname, GPipe *igp, volatile int *pid);
505
void gClosen(GPipe *pajp);
506
int gOpen(GProc *proc,
507
char **argv, const char *what, char **env, char *cname,
508
const char *user, const char *authfile, GPipe *igp);
509
int gClose(GProc *proc, GPipe *gp, int force);
511
void gSendInt(int val);
513
int gRecvCmd(int *cmd);
514
void gSendArr(int len, const char *data);
515
char *gRecvArr(int *len);
516
int gRecvStrBuf(char *buf);
517
int gRecvArrBuf(char *buf);
518
void gSendStr(const char *buf);
519
void gSendNStr(const char *buf, int len); /* exact len, buf != 0 */
520
void gSendStrN(const char *buf, int len); /* maximal len */
521
char *gRecvStr(void);
522
void gSendArgv(char **argv);
523
void gSendStrArr(int len, char **data);
524
char **gRecvStrArr(int *len);
525
char **gRecvArgv(void);
528
#define GCONV_NORMAL 0
529
#define GCONV_HIDDEN 1
532
#define GCONV_PASS_ND 4
533
#define GCONV_BINARY 5
534
typedef char *(*GConvFunc)(int what, const char *prompt);
535
int verify(GConvFunc gconv, int rootok);
536
int startClient(volatile int *pid);
537
void clientExited(void);
538
void sessionExit(int status) ATTR_NORETURN;
540
int changeUser(const char *user, const char *authfile);
541
extern char **userEnviron, **systemEnviron;
542
extern char *curuser, *curpass, *curtype, *newpass,
543
*dmrcuser, *curdmrc, *newdmrc;
544
extern int cursource;
545
#define PWSRC_MANUAL 0
546
#define PWSRC_AUTOLOGIN 1
547
#define PWSRC_RELOGIN 2
550
char **prepareServerArgv(struct display *d, const char *args);
551
void startServer(struct display *d);
552
void abortStartServer(struct display *d);
553
void startServerSuccess(void);
554
void startServerFailed(void);
555
void startServerTimeout(void);
556
extern struct display *startingServer;
557
extern time_t serverTimeout;
559
void waitForServer(struct display *d);
560
void resetServer(struct display *d);
561
int pingServer(struct display *d);
562
extern struct _XDisplay *dpy;
565
void *Calloc(size_t nmemb, size_t size);
566
void *Malloc(size_t size);
567
void *Realloc(void *ptr, size_t size);
568
void wipeStr(char *str);
569
int strCmp(const char *s1, const char *s2);
571
int strnlen(const char *s, int max);
573
int strNDup(char **dst, const char *src, int len);
574
int strDup(char **dst, const char *src);
575
int arrLen(char **arr);
576
void freeStrArr(char **arr);
577
char **initStrArr(char **arr);
578
char **xCopyStrArr(int rn, char **arr);
579
/* Note: the following functions free the old data even in case of failure */
580
int reStrN(char **dst, const char *src, int len);
581
int reStr(char **dst, const char *src);
582
int strApp(char **dst, ...);
583
char **addStrArr(char **arr, const char *str, int len);
584
char **parseArgs(char **argv, const char *string);
586
char **setEnv(char **e, const char *name, const char *value);
587
char **putEnv(const char *string, char **env);
588
const char *getEnv(char **e, const char *name);
589
const char *localHostname(void);
590
int reader(int fd, void *buf, int len);
591
int writer(int fd, const void *buf, int len);
592
int fGets(char *buf, int max, FILE *f);
593
time_t mTime(const char *fn);
594
void randomStr(char *s);
595
int hexToBinary(char *out, const char *in);
596
void listSessions(int flags, struct display *d, void *ctx,
597
void (*emitXSess)(struct display *, struct display *, void *),
598
void (*emitTTYSess)(STRUCTUTMP *, struct display *, void *));
599
int anyUserLogins(int exclude_uid);
606
char *expandMacros(const char *str, struct expando *expandos);
609
char *iniLoad(const char *fname);
610
int iniSave(const char *data, const char *fname);
611
char *iniEntry(char *data, const char *section, const char *key, const char *value);
612
char *iniMerge(char *data, const char *newdata);
615
int getBootOptions(char ***opts, int *def, int *cur);
616
int setBootOption(const char *opt, SdRec *sdr);
617
void commitBootOption(void);
620
CARD8 *netaddrAddress(char *netaddrp, int *lenp);
621
CARD8 *netaddrPort(char *netaddrp, int *lenp);
622
int convertAddr(char *saddr, int *len, CARD8 **addr);
623
int netaddrFamily(char *netaddrp);
624
int addressEqual(char *a1, int len1, char *a2, int len2);
629
char *networkAddressToHostname(CARD16 connectionType, ARRAY8Ptr connectionAddress);
630
void sendFailed(struct display *d, const char *reason);
631
void initXdmcp(void);
635
ARRAY8Ptr isAccepting(struct sockaddr *from, int fromlen, CARD16 displayNumber);
636
ARRAY8Ptr chooseAuthentication(ARRAYofARRAY8Ptr authenticationNames);
637
int checkAuthentication(struct protoDisplay *pdpy, ARRAY8Ptr displayID, ARRAY8Ptr name, ARRAY8Ptr data);
638
int selectAuthorizationTypeIndex(ARRAY8Ptr authenticationName, ARRAYofARRAY8Ptr authorizationNames);
639
int selectConnectionTypeIndex(ARRAY16Ptr connectionTypes, ARRAYofARRAY8Ptr connectionAddresses);
640
int isWilling(ARRAY8Ptr addr, CARD16 connectionType, ARRAY8Ptr authenticationName, ARRAY8Ptr status, xdmOpCode type);
643
void disposeProtoDisplay(struct protoDisplay *pdpy);
645
struct protoDisplay *findProtoDisplay(XdmcpNetaddr address, int addrlen,
646
CARD16 displayNumber);
647
struct protoDisplay *newProtoDisplay(XdmcpNetaddr address, int addrlen,
648
CARD16 displayNumber,
649
CARD16 connectionType,
650
ARRAY8Ptr connectionAddress,
653
#define FamilyBroadcast 0xffff
654
typedef void (*ChooserFunc)(CARD16 connectionType, ARRAY8Ptr addr, char *closure);
655
typedef void (*ListenFunc)(ARRAY8Ptr addr, void **closure);
658
ARRAY8Ptr getLocalAddress(void);
659
int acceptableDisplayAddress(ARRAY8Ptr clientAddress, CARD16 connectionType, xdmOpCode type);
660
int forEachMatchingIndirectHost(ARRAY8Ptr clientAddress, ARRAY8Ptr clientPort, CARD16 connectionType,
661
ChooserFunc function, char *closure);
662
void scanAccessDatabase(int force);
663
int useChooser(ARRAY8Ptr clientAddress, CARD16 connectionType);
664
void forEachChooserHost(ARRAY8Ptr clientAddress, CARD16 connectionType, ChooserFunc function, char *closure);
665
void forEachListenAddr(ListenFunc listenfunction, ListenFunc mcastfcuntion, void **closure);
668
time_t disposeIndirectHosts(void);
669
ARRAY8Ptr indirectChoice(ARRAY8Ptr clientAddress, ARRAY8Ptr clientPort, CARD16 connectionType);
670
int checkIndirectChoice(ARRAY8Ptr clientAddress, ARRAY8Ptr clientPort, CARD16 connectionType);
671
void registerIndirectChoice(ARRAY8Ptr clientAddress, ARRAY8Ptr clientPort, CARD16 connectionType,
675
/* socket.c or streams.c */
676
void updateListenSockets(void);
677
int anyListenSockets(void);
678
int processListenSockets(fd_set *reads);
681
void processRequestSocket(int fd);
686
void sessreg(struct display *d, int pid, const char *user, int uid);