summaryrefslogtreecommitdiff
path: root/daemon/gdm.h
blob: 21a311df7674a4e41a659db1e41c336e6e46e246 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
/* GDM - The GNOME Display Manager
 * Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#ifndef GDM_H
#define GDM_H

#include <glib.h>
#include <glib/gstdio.h>
#include <X11/Xlib.h>
#include <X11/Xmd.h>
#include <X11/Xauth.h>
#include <netinet/in.h>
#include <time.h>

#define GDM_MAX_PASS 256	/* Define a value for password length. Glibc
				 * leaves MAX_PASS undefined. */

#define STX 0x2			/* Start of txt */
#define BEL 0x7			/* Bell, used to interrupt login for
				 * say timed login or something similar */

#define TYPE_STATIC 1		/* X server defined in GDM configuration */
#define TYPE_XDMCP 2		/* Remote display/Xserver */
#define TYPE_FLEXI 3		/* Local Flexi X server */
#define TYPE_FLEXI_XNEST 4	/* Local Flexi Xnest server */
#define TYPE_XDMCP_PROXY 5	/* Proxy X server for XDMCP */

#define SERVER_IS_LOCAL(d) ((d)->type == TYPE_STATIC || \
			    (d)->type == TYPE_FLEXI || \
			    (d)->type == TYPE_FLEXI_XNEST || \
			    (d)->type == TYPE_XDMCP_PROXY)
#define SERVER_IS_FLEXI(d) ((d)->type == TYPE_FLEXI || \
			    (d)->type == TYPE_FLEXI_XNEST || \
			    (d)->type == TYPE_XDMCP_PROXY)
#define SERVER_IS_PROXY(d) ((d)->type == TYPE_FLEXI_XNEST || \
			    (d)->type == TYPE_XDMCP_PROXY)
#define SERVER_IS_XDMCP(d) ((d)->type == TYPE_XDMCP || \
			    (d)->type == TYPE_XDMCP_PROXY)

/* These are the servstat values, also used as server
 * process exit codes */
#define SERVER_TIMEOUT 2	/* Server didn't start */
#define SERVER_DEAD 250		/* Server stopped */
#define SERVER_PENDING 251	/* Server started but not ready for connections yet */
#define SERVER_RUNNING 252	/* Server running and ready for connections */
#define SERVER_ABORT 253	/* Server failed badly. Suspending display. */

/* DO NOTE USE 1, that's used as error if x connection fails usually */
/* Note that there is no reason why these were a power of two, and note
 * that they have to fit in 256 */
/* These are the exit codes */
#define DISPLAY_REMANAGE 2	/* Restart display */
#define DISPLAY_ABORT 4		/* Houston, we have a problem */
#define DISPLAY_REBOOT 8	/* Rebewt */
#define DISPLAY_HALT 16		/* Halt */
#define DISPLAY_SUSPEND 17	/* Suspend (don't use, use the interrupt) */
#define DISPLAY_CHOSEN 20	/* successful chooser session,
				   restart display */
#define DISPLAY_RUN_CHOOSER 30	/* Run chooser */
#define DISPLAY_XFAILED 64	/* X failed */
#define DISPLAY_GREETERFAILED 65 /* greeter failed (crashed) */
#define DISPLAY_RESTARTGREETER 127 /* Restart greeter */
#define DISPLAY_RESTARTGDM 128	/* Restart GDM */

enum {
	DISPLAY_UNBORN /* Not yet started */,
	DISPLAY_ALIVE /* Yay! we're alive (non-XDMCP) */,
	XDMCP_PENDING /* Pending XDMCP display */,
	XDMCP_MANAGED /* Managed XDMCP display */,
	DISPLAY_DEAD /* Left for dead */,
	DISPLAY_CONFIG /* in process of being configured */
};

/* Opcodes for the highly sophisticated protocol used for
 * daemon<->greeter communications */

/* This will change if there are incompatible
 * protocol changes */
#define GDM_GREETER_PROTOCOL_VERSION "3"

#define GDM_MSG        'D'
#define GDM_NOECHO     'U'
#define GDM_PROMPT     'N'
#define GDM_SESS       'G'
#define GDM_LANG       '&'
#define GDM_SSESS      'C'
#define GDM_SLANG      'R'
#define GDM_RESET      'A'
#define GDM_QUIT       'P'
/* Well these aren't as nice as above, oh well */
#define GDM_STARTTIMER 's'
#define GDM_STOPTIMER  'S'
#define GDM_SETLOGIN   'l' /* this just sets the login to be this, just for
			      the greeters knowledge */
#define GDM_DISABLE    '-' /* disable the login screen */
#define GDM_ENABLE     '+' /* enable the login screen */
#define GDM_RESETOK    'r' /* reset but don't shake */
#define GDM_NEEDPIC    '#' /* need a user picture?, sent after greeter
			    *  is started */
#define GDM_READPIC    '%' /* Send a user picture in a temp file */
#define GDM_ERRBOX     'e' /* Puts string in the error box */
#define GDM_ERRDLG     'E' /* Puts string up in an error dialog */
#define GDM_NOFOCUS    'f' /* Don't focus the login window (optional) */
#define GDM_FOCUS      'F' /* Allow focus on the login window again (optional) */
#define GDM_SAVEDIE    '!' /* Save wm order and die (and set busy cursor) */
#define GDM_QUERY_CAPSLOCK 'Q' /* Is capslock on? */

/* Different login interruptions */
#define GDM_INTERRUPT_TIMED_LOGIN 'T'
#define GDM_INTERRUPT_CONFIGURE   'C'
#define GDM_INTERRUPT_SUSPEND     'S'
#define GDM_INTERRUPT_SELECT_USER 'U'
#define GDM_INTERRUPT_LOGIN_SOUND 'L'
#define GDM_INTERRUPT_THEME       'H'
#define GDM_INTERRUPT_CUSTOM_CMD  'M'
#define GDM_INTERRUPT_CANCEL      'X'

/* List delimiter for config file lists */
#define GDM_DELIMITER_MODULES ":"
#define GDM_DELIMITER_THEMES "/:"

/* The dreaded miscellaneous category */
#define FIELD_SIZE 256
#define PIPE_SIZE 4096

/*
 * The following section contains keys used by the GDM configuration files.
 * The key/value pairs defined in the GDM configuration files are considered
 * "stable" interface and should only change in ways that are backwards
 * compatible.  Please keep this in mind when changing GDM configuration.
 * 
 * Developers who add new configuration options should ensure that they do the
 * following:
 * 
 * + Edit the config/gdm.conf file to include the default setting.
 *
 * + Specify the same default in this file as in the config/gdm.conf.in file.
 *
 * + Update the gdm_config_init function in daemon/gdmconfig.c to add the
 *   new key.  Include some documentation about the new key, following the
 *   style of existing comments.
 *
 * + Add any validation to the _gdm_set_value_string, _gdm_set_value_int,
 *   and/or _gdm_set_value_bool functions (depending on the type of the new
 *   key) in gdmconfig.c, if validation is needed.
 *
 * + If GDM_UPDATE_CONFIG should not respond to this configuration setting,
 *   update the update_config function in gdmconfig.c to return FALSE for
 *   this key.  Examples include changing the PidFile, ServAuthDir, or
 *   other values that GDM should not change until it is restarted.  If 
 *   this is true, the next bullet can be ignored.
 *
 * + If the option should cause the greeter (gdmlogin/gdmgreeter) program to
 *   be updated immediately, make sure to update the appropriate 
 *   _gdm_set_value_* function in gdmconfig.c.  This function calls the
 *   notify_displays_* function to call when this value is changed, so you
 *   will need to add your new config value to the list of values sending
 *   such notification.  Supporting logic will need to be added to
 *   gdm_slave_handle_notify function in slave.c to process the notify.
 *   It should be clear to see how to do this from the existing code.
 *
 * + Add the key to the gdm_read_config and gdm_reread_config functions in 
 *   gui/gdmlogin.c, gui/gdmchooser.c, and gui/greeter/greeter.c
 *   if the key is used by those programs.  Note that all GDM slaves load
 *   all their configuration data between calls to gdmcomm_comm_bulk_start()
 *   and gdmcomm_comm_bulk_stop().  This makes sure that the slave only uses
 *   a single sockets connection to get all configuration data.  If a new
 *   config value is read by a slave, make sure to load the key in this
 *   code section for best performance.
 *
 * + The gui/gdmsetup.c program should be updated to support the new option
 *   unless there's a good reason not to (like it is a configuration value
 *   that only someone who really knows what they are doing should change
 *   like GDM_KEY_PID_FILE).
 * 
 * + Currently GDM treats any key in the "gui" and "greeter" categories,
 *   and security/PamStack as available for per-display configuration.  
 *   If a key is appropriate for per-display configuration, and is not
 *   in the "gui" or "greeter" categories, then it will need to be added
 *   to the gdm_config_key_to_string_per_display function.  It may make
 *   sense for some keys used by the daemon to be per-display so this
 *   will need to be coded (refer to GDM_KEY_PAM_STACK for an example).
 *
 * + Update the docs/C/gdm.xml file to include information about the new
 *   option.  Include information about any other interfaces (such as 
 *   ENVIRONMENT variables) that may affect the configuration option.
 *   Patches without documentation will not be accepted.
 *
 * Please do this work *before* submitting an patch.  Patches that are not
 * complete will not likely be accepted.
 */

/* Configuration constants */
#define GDM_KEY_CHOOSER "daemon/Chooser=" LIBEXECDIR "/gdmchooser"
#define GDM_KEY_AUTOMATIC_LOGIN_ENABLE "daemon/AutomaticLoginEnable=false"
#define GDM_KEY_AUTOMATIC_LOGIN "daemon/AutomaticLogin="
/* The SDTLOGIN feature is Solaris specific, and causes the Xserver to be
 * run with user permissionsinstead of as root, which adds security but
 * disables the AlwaysRestartServer option as highlighted in the gdm
 * documentation */
#ifdef sun
#define GDM_KEY_ALWAYS_RESTART_SERVER "daemon/AlwaysRestartServer=true"
#else
#define GDM_KEY_ALWAYS_RESTART_SERVER "daemon/AlwaysRestartServer=false"
#endif
#define GDM_KEY_GREETER "daemon/Greeter=" LIBEXECDIR "/gdmlogin"
#define GDM_KEY_REMOTE_GREETER "daemon/RemoteGreeter=" LIBEXECDIR "/gdmlogin"
#define GDM_KEY_ADD_GTK_MODULES "daemon/AddGtkModules=false"
#define GDM_KEY_GTK_MODULES_LIST "daemon/GtkModulesList="
#define GDM_KEY_GROUP "daemon/Group=gdm"
#define GDM_KEY_HALT "daemon/HaltCommand=" HALT_COMMAND
#define GDM_KEY_DISPLAY_INIT_DIR "daemon/DisplayInitDir=" GDMCONFDIR "/Init"
#define GDM_KEY_KILL_INIT_CLIENTS "daemon/KillInitClients=true"
#define GDM_KEY_LOG_DIR "daemon/LogDir=" LOGDIR
#define GDM_KEY_PATH "daemon/DefaultPath=" GDM_USER_PATH
#define GDM_KEY_PID_FILE "daemon/PidFile=/var/run/gdm.pid"
#define GDM_KEY_POSTSESSION "daemon/PostSessionScriptDir=" GDMCONFDIR "/PostSession/"
#define GDM_KEY_PRESESSION "daemon/PreSessionScriptDir=" GDMCONFDIR "/PreSession/"
#define GDM_KEY_POSTLOGIN "daemon/PostLoginScriptDir=" GDMCONFDIR "/PreSession/"
#define GDM_KEY_FAILSAFE_XSERVER "daemon/FailsafeXServer="
#define GDM_KEY_X_KEEPS_CRASHING "daemon/XKeepsCrashing=" GDMCONFDIR "/XKeepsCrashing"
#define GDM_KEY_REBOOT  "daemon/RebootCommand=" REBOOT_COMMAND
#define GDM_KEY_CUSTOM_CMD_TEMPLATE "customcommand/CustomCommand"
#define GDM_KEY_CUSTOM_CMD_LABEL_TEMPLATE "customcommand/CustomCommandLabel"
#define GDM_KEY_CUSTOM_CMD_LR_LABEL_TEMPLATE "customcommand/CustomCommandLRLabel"
#define GDM_KEY_CUSTOM_CMD_TEXT_TEMPLATE "customcommand/CustomCommandText"
#define GDM_KEY_CUSTOM_CMD_TOOLTIP_TEMPLATE "customcommand/CustomCommandTooltip"
#define GDM_KEY_CUSTOM_CMD_NO_RESTART_TEMPLATE "customcommand/CustomCommandNoRestart"
#define GDM_KEY_ROOT_PATH "daemon/RootPath=/sbin:/usr/sbin:" GDM_USER_PATH
#define GDM_KEY_SERV_AUTHDIR "daemon/ServAuthDir=" AUTHDIR
#define GDM_KEY_SESSION_DESKTOP_DIR "daemon/SessionDesktopDir=/etc/X11/sessions/:" DMCONFDIR "/Sessions/:" DATADIR "/gdm/BuiltInSessions/:" DATADIR "/xsessions/"
#define GDM_KEY_BASE_XSESSION "daemon/BaseXsession=" GDMCONFDIR "/Xsession"
#define GDM_KEY_DEFAULT_SESSION "daemon/DefaultSession=gnome.desktop"
#define GDM_KEY_SUSPEND "daemon/SuspendCommand=" SUSPEND_COMMAND

#define GDM_KEY_USER_AUTHDIR "daemon/UserAuthDir="
#define GDM_KEY_USER_AUTHDIR_FALLBACK "daemon/UserAuthFBDir=/tmp"
#define GDM_KEY_USER_AUTHFILE "daemon/UserAuthFile=.Xauthority"
#define GDM_KEY_USER "daemon/User=gdm"
#define GDM_KEY_CONSOLE_NOTIFY "daemon/ConsoleNotify=true"

#define GDM_KEY_DOUBLE_LOGIN_WARNING "daemon/DoubleLoginWarning=true"
#define GDM_KEY_ALWAYS_LOGIN_CURRENT_SESSION "daemon/AlwaysLoginCurrentSession=false"

#define GDM_KEY_DISPLAY_LAST_LOGIN "daemon/DisplayLastLogin=false"

#define GDM_KEY_TIMED_LOGIN_ENABLE "daemon/TimedLoginEnable=false"
#define GDM_KEY_TIMED_LOGIN "daemon/TimedLogin="
#define GDM_KEY_TIMED_LOGIN_DELAY "daemon/TimedLoginDelay=30"

#define GDM_KEY_FLEXI_REAP_DELAY_MINUTES "daemon/FlexiReapDelayMinutes=5"

#define GDM_KEY_STANDARD_XSERVER "daemon/StandardXServer=" X_SERVER
#define GDM_KEY_FLEXIBLE_XSERVERS "daemon/FlexibleXServers=5"
#define GDM_KEY_DYNAMIC_XSERVERS "daemon/DynamicXServers=false"
#define GDM_KEY_XNEST "daemon/Xnest=" X_SERVER_PATH "/Xnest -name Xnest"
/* Keys for automatic VT allocation rather then letting it up to the
 * X server */
#define GDM_KEY_FIRST_VT "daemon/FirstVT=7"
#define GDM_KEY_VT_ALLOCATION "daemon/VTAllocation=true"

#define GDM_KEY_CONSOLE_CANNOT_HANDLE "daemon/ConsoleCannotHandle=am,ar,az,bn,el,fa,gu,hi,ja,ko,ml,mr,pa,ta,zh"

/* How long to wait before assuming an Xserver has timed out */
#define GDM_KEY_XSERVER_TIMEOUT "daemon/GdmXserverTimeout=10"

/* Per server definitions */
#define GDM_KEY_SERVER_PREFIX "server-"
#define GDM_KEY_SERVER_NAME "name=Standard server"
#define GDM_KEY_SERVER_COMMAND "command=" X_SERVER
/* runnable as flexi server */
#define GDM_KEY_SERVER_FLEXIBLE "flexible=true"
/* choosable from the login screen */
#define GDM_KEY_SERVER_CHOOSABLE "choosable=false"
/* Login is handled by gdm, otherwise it's a remote server */
#define GDM_KEY_SERVER_HANDLED "handled=true"
/* Instead of the greeter run the chooser */
#define GDM_KEY_SERVER_CHOOSER "chooser=false"
/* select a nice level to run the X server at */
#define GDM_KEY_SERVER_PRIORITY "priority=0"

#define GDM_KEY_ALLOW_ROOT "security/AllowRoot=true"
#define GDM_KEY_ALLOW_REMOTE_ROOT "security/AllowRemoteRoot=true"
#define GDM_KEY_ALLOW_REMOTE_AUTOLOGIN "security/AllowRemoteAutoLogin=false"
#define GDM_KEY_USER_MAX_FILE "security/UserMaxFile=65536"
#define GDM_KEY_RELAX_PERM "security/RelaxPermissions=0"
#define GDM_KEY_CHECK_DIR_OWNER "security/CheckDirOwner=true"
#define GDM_KEY_SUPPORT_AUTOMOUNT "security/SupportAutomount=false"
#define GDM_KEY_RETRY_DELAY "security/RetryDelay=1"
#define GDM_KEY_DISALLOW_TCP "security/DisallowTCP=true"
#define GDM_KEY_PAM_STACK "security/PamStack=gdm"

#define GDM_KEY_NEVER_PLACE_COOKIES_ON_NFS "security/NeverPlaceCookiesOnNFS=true"
#define GDM_KEY_PASSWORD_REQUIRED "security/PasswordRequired=false"

#define GDM_KEY_XDMCP "xdmcp/Enable=false"
#define GDM_KEY_MAX_PENDING "xdmcp/MaxPending=4"
#define GDM_KEY_MAX_SESSIONS "xdmcp/MaxSessions=16"
#define GDM_KEY_MAX_WAIT "xdmcp/MaxWait=15"
#define GDM_KEY_DISPLAYS_PER_HOST "xdmcp/DisplaysPerHost=2"
#define GDM_KEY_UDP_PORT "xdmcp/Port=177"
#define GDM_KEY_INDIRECT "xdmcp/HonorIndirect=true"
#define GDM_KEY_MAX_INDIRECT "xdmcp/MaxPendingIndirect=4"
#define GDM_KEY_MAX_WAIT_INDIRECT "xdmcp/MaxWaitIndirect=15"
#define GDM_KEY_PING_INTERVAL "xdmcp/PingIntervalSeconds=15"
#define GDM_KEY_WILLING "xdmcp/Willing=" GDMCONFDIR "/Xwilling"

#define GDM_KEY_XDMCP_PROXY "xdmcp/EnableProxy=false"
#define GDM_KEY_XDMCP_PROXY_XSERVER "xdmcp/ProxyXServer="
#define GDM_KEY_XDMCP_PROXY_RECONNECT "xdmcp/ProxyReconnect="

#define GDM_KEY_GTK_THEME "gui/GtkTheme=Default"
#define GDM_KEY_GTKRC "gui/GtkRC=" DATADIR "/themes/Default/gtk-2.0/gtkrc"
#define GDM_KEY_MAX_ICON_WIDTH "gui/MaxIconWidth=128"
#define GDM_KEY_MAX_ICON_HEIGHT "gui/MaxIconHeight=128"

#define GDM_KEY_ALLOW_GTK_THEME_CHANGE "gui/AllowGtkThemeChange=true"
#define GDM_KEY_GTK_THEMES_TO_ALLOW "gui/GtkThemesToAllow=all"

#define GDM_KEY_BROWSER "greeter/Browser=false"
#define GDM_KEY_INCLUDE "greeter/Include="
#define GDM_KEY_EXCLUDE "greeter/Exclude=bin,daemon,adm,lp,sync,shutdown,halt,mail,news,uucp,operator,nobody,gdm,postgres,pvm,rpm,nfsnobody,pcap"
#define GDM_KEY_INCLUDE_ALL "greeter/IncludeAll=false"
#define GDM_KEY_MINIMAL_UID "greeter/MinimalUID=100"
#define GDM_KEY_DEFAULT_FACE "greeter/DefaultFace=" PIXMAPDIR "/nobody.png"
#define GDM_KEY_GLOBAL_FACE_DIR "greeter/GlobalFaceDir=" DATADIR "/pixmaps/faces/"
#define GDM_KEY_LOCALE_FILE "greeter/LocaleFile=" GDMLOCALEDIR "/locale.alias"
#define GDM_KEY_LOGO "greeter/Logo=" PIXMAPDIR "/gdm-foot-logo.png"
#define GDM_KEY_CHOOSER_BUTTON_LOGO "greeter/ChooserButtonLogo=" PIXMAPDIR "/gdm-foot-logo.png"
#define GDM_KEY_QUIVER "greeter/Quiver=true"
#define GDM_KEY_SYSTEM_MENU "greeter/SystemMenu=true"
#define GDM_KEY_CONFIGURATOR "daemon/Configurator=" SBINDIR "/gdmsetup --disable-sound --disable-crash-dialog"
#define GDM_KEY_CONFIG_AVAILABLE "greeter/ConfigAvailable=true"
#define GDM_KEY_CHOOSER_BUTTON "greeter/ChooserButton=true"
#define GDM_KEY_TITLE_BAR "greeter/TitleBar=true"

/*
 * For backwards compatibility, do not set values for DEFAULT_WELCOME or 
 * DEFAULT_REMOTEWELCOME.  This will cause these values to always be 
 * read from the config file, and will cause them to return FALSE if
 * no value is set in the config file.  We want the value "FALSE" if
 * the values don't exist in the config file.  The daemon will compare
 * the Welcome/RemoveWelcome value with the default string and 
 * automatically translate the text if the string is the same as the
 * default string.  We set the default values of GDM_KEY_WELCOME and
 * GDM_KEY_REMOTEWELCOME so that the default value is returned when
 * you run GET_CONFIG on these keys.
 */
#define GDM_DEFAULT_WELCOME_MSG "Welcome"
#define GDM_DEFAULT_REMOTE_WELCOME_MSG "Welcome to %n"

#define GDM_KEY_DEFAULT_WELCOME "greeter/DefaultWelcome=" 
#define GDM_KEY_DEFAULT_REMOTE_WELCOME "greeter/DefaultRemoteWelcome=" 
#define GDM_KEY_WELCOME "greeter/Welcome=" GDM_DEFAULT_WELCOME_MSG
#define GDM_KEY_REMOTE_WELCOME "greeter/RemoteWelcome=" GDM_DEFAULT_REMOTE_WELCOME_MSG
#define GDM_KEY_XINERAMA_SCREEN "greeter/XineramaScreen=0"
#define GDM_KEY_BACKGROUND_PROGRAM "greeter/BackgroundProgram="
#define GDM_KEY_RUN_BACKGROUND_PROGRAM_ALWAYS "greeter/RunBackgroundProgramAlways=false"
#define GDM_KEY_BACKGROUND_PROGRAM_INITIAL_DELAY "greeter/BackgroundProgramInitialDelay=30"
#define GDM_KEY_RESTART_BACKGROUND_PROGRAM "greeter/RestartBackgroundProgram=true"
#define GDM_KEY_BACKGROUND_PROGRAM_RESTART_DELAY "greeter/BackgroundProgramRestartDelay=30"
#define GDM_KEY_BACKGROUND_IMAGE "greeter/BackgroundImage="
#define GDM_KEY_BACKGROUND_COLOR "greeter/BackgroundColor=#76848F"
#define GDM_KEY_BACKGROUND_TYPE "greeter/BackgroundType=2"
#define GDM_KEY_BACKGROUND_SCALE_TO_FIT "greeter/BackgroundScaleToFit=true"
#define GDM_KEY_BACKGROUND_REMOTE_ONLY_COLOR "greeter/BackgroundRemoteOnlyColor=true"
#define GDM_KEY_LOCK_POSITION "greeter/LockPosition=false"
#define GDM_KEY_SET_POSITION "greeter/SetPosition=false"
#define GDM_KEY_POSITION_X "greeter/PositionX=0"
#define GDM_KEY_POSITION_Y "greeter/PositionY=0"
#define GDM_KEY_USE_24_CLOCK "greeter/Use24Clock=auto"
#define GDM_KEY_ENTRY_CIRCLES "greeter/UseCirclesInEntry=false"
#define GDM_KEY_ENTRY_INVISIBLE "greeter/UseInvisibleInEntry=false"
#define GDM_KEY_GRAPHICAL_THEME "greeter/GraphicalTheme=circles"
#define GDM_KEY_GRAPHICAL_THEMES "greeter/GraphicalThemes=circles"
#define GDM_KEY_GRAPHICAL_THEME_RAND "greeter/GraphicalThemeRand=false"
#define GDM_KEY_GRAPHICAL_THEME_DIR "greeter/GraphicalThemeDir=" DATADIR "/gdm/themes/"
#define GDM_KEY_GRAPHICAL_THEMED_COLOR "greeter/GraphicalThemedColor=#76848F"

#define GDM_KEY_INFO_MSG_FILE "greeter/InfoMsgFile="
#define GDM_KEY_INFO_MSG_FONT "greeter/InfoMsgFont="

#define GDM_KEY_PRE_FETCH_PROGRAM "greeter/PreFetchProgram="

#define GDM_KEY_SOUND_ON_LOGIN "greeter/SoundOnLogin=true"
#define GDM_KEY_SOUND_ON_LOGIN_SUCCESS "greeter/SoundOnLoginSuccess=false"
#define GDM_KEY_SOUND_ON_LOGIN_FAILURE "greeter/SoundOnLoginFailure=false"
#define GDM_KEY_SOUND_ON_LOGIN_FILE "greeter/SoundOnLoginFile="
#define GDM_KEY_SOUND_ON_LOGIN_SUCCESS_FILE "greeter/SoundOnLoginSuccessFile="
#define GDM_KEY_SOUND_ON_LOGIN_FAILURE_FILE "greeter/SoundOnLoginFailureFile="
#define GDM_KEY_SOUND_PROGRAM "daemon/SoundProgram=" SOUND_PROGRAM

#define GDM_KEY_SCAN_TIME "chooser/ScanTime=4"
#define GDM_KEY_DEFAULT_HOST_IMG "chooser/DefaultHostImg=" PIXMAPDIR "/nohost.png"
#define GDM_KEY_HOST_IMAGE_DIR "chooser/HostImageDir=" DATADIR "/hosts/"
#define GDM_KEY_HOSTS "chooser/Hosts="
#define GDM_KEY_MULTICAST "chooser/Multicast=true"
#define GDM_KEY_MULTICAST_ADDR "chooser/MulticastAddr=ff02::1"
#define GDM_KEY_BROADCAST "chooser/Broadcast=true"
#define GDM_KEY_ALLOW_ADD "chooser/AllowAdd=true"

#define GDM_KEY_DEBUG "debug/Enable=false"
#define GDM_KEY_DEBUG_GESTURES "debug/Gestures=false"

#define GDM_KEY_SECTION_GREETER "greeter"
#define GDM_KEY_SECTION_SERVERS "servers"

#define GDM_KEY_SHOW_GNOME_FAILSAFE "greeter/ShowGnomeFailsafeSession=true"
#define GDM_KEY_SHOW_XTERM_FAILSAFE "greeter/ShowXtermFailsafeSession=true"
#define GDM_KEY_SHOW_LAST_SESSION "greeter/ShowLastSession=true"

#define GDM_SESSION_FAILSAFE_GNOME "GDM_Failsafe.GNOME"
#define GDM_SESSION_FAILSAFE_XTERM "GDM_Failsafe.XTERM"

/* FIXME: will support these builtin types later */
#define GDM_SESSION_DEFAULT "default"
#define GDM_SESSION_CUSTOM "custom"
#define GDM_SESSION_FAILSAFE "failsafe"

#define GDM_STANDARD "Standard"

#define GDM_RESPONSE_CANCEL "GDM_RESPONSE_CANCEL"

#ifndef TYPEDEF_GDM_CONNECTION
#define TYPEDEF_GDM_CONNECTION
typedef struct _GdmConnection GdmConnection;
#endif  /* TYPEDEF_GDM_CONNECTION */

#ifndef TYPEDEF_GDM_CUSTOM_CMD
#define TYPEDEF_GDM_CUSTOM_CMD
typedef struct _GdmCustomCmd GdmCustomCmd;
#endif /* TYPEDEF_GDM_CUSTOM_CMD */
struct _GdmCustomCmd {
    gchar *command; /* command(s) to execute */
    gchar *command_label; /* button/menu item label */
    gchar *command_lr_label; /* radio button/list item label */
    gchar *command_text; /* warning dialog text */
    gchar *command_tooltip; /* tooltip string */
    gboolean command_no_restart; /* no restart flag */
};

#define GDM_CUSTOM_COMMAND_MAX 10 /* maximum number of supported custom commands */

/* Values between GDM_LOGOUT_ACTION_CUSTOM_CMD_FIRST and 
   GDM_LOGOUT_ACTION_CUSTOM_CMD_LAST are reserved and should not be used */
typedef enum {
	GDM_LOGOUT_ACTION_NONE = 0,
	GDM_LOGOUT_ACTION_HALT,
	GDM_LOGOUT_ACTION_REBOOT,
	GDM_LOGOUT_ACTION_SUSPEND,
	GDM_LOGOUT_ACTION_CUSTOM_CMD_FIRST,
	GDM_LOGOUT_ACTION_CUSTOM_CMD_LAST = GDM_LOGOUT_ACTION_CUSTOM_CMD_FIRST + GDM_CUSTOM_COMMAND_MAX - 1,
	GDM_LOGOUT_ACTION_LAST
} GdmLogoutAction;

#ifndef TYPEDEF_GDM_DISPLAY
#define TYPEDEF_GDM_DISPLAY
typedef struct _GdmDisplay GdmDisplay;
#endif /* TYPEDEF_GDM_DISPLAY */

/* Use this to get the right authfile name */
#define GDM_AUTHFILE(display) \
	(display->authfile_gdm != NULL ? display->authfile_gdm : display->authfile)

#ifdef sun
#define SDTLOGIN_DIR "/var/dt/sdtlogin"
#endif

struct _GdmDisplay {
    CARD32 sessionid;
    Display *dsp;
    gchar *authfile; /* authfile for the server */
    gchar *authfile_gdm; /* authfile readable by gdm user
			    if necessary */
    GSList *auths; 
    GSList *local_auths; 
    gchar *userauth;
    gboolean authfb;
    time_t last_auth_touch;
    gchar *command;
    gboolean failsafe_xserver;
    gboolean use_chooser; /* run chooser instead of greeter */
    gchar *chosen_hostname; /* locally chosen hostname if not NULL,
			       "-query chosen_hostname" is appened to server command line */
    guint indirect_id;
    gchar *cookie;
    gchar *bcookie;
    gchar *name;
    gchar *hostname;
    struct in_addr addr;
#ifdef ENABLE_IPV6
    struct in6_addr addr6;
    struct sockaddr_storage *addrs; /* array of addresses */
#else
    struct in_addr *addrs; /* array of addresses */
#endif
    int addrtype;        /* Specifying the variable used, addr or addr6  */
    int addr_count; /* number of addresses in array */
    /* Note that the above may in fact be empty even though
       addr is set, these are just extra addresses
       (it could also contain addr for all we know) */

    guint8 dispstat;
    guint16 dispnum;
	gboolean removeconf;
    guint8 servstat;
    time_t starttime;
    time_t managetime;
    guint8 type;
    pid_t greetpid;
    pid_t servpid;
    pid_t sesspid;
    int last_sess_status; /* status returned by last session */
    pid_t slavepid;
    pid_t chooserpid;
    time_t acctime;

    gboolean handled;
    gboolean tcp_disallowed;

    int priority;
    int vt;

    gboolean busy_display;

    gboolean attached;  /* Display is physically attached to the machine. */
                        /* TYPE_XDMCP would have this FALSE, eg. */

    time_t last_start_time;
    time_t last_loop_start_time;
    gint retry_count;

    int sleep_before_run;

    time_t last_x_failed;
    int x_faileds;

    gboolean try_different_greeter;

    gboolean logged_in; /* TRUE if someone is logged in */
    char *login;

    gboolean timed_login_ok;

    int screenx;
    int screeny;
    int screenwidth; /* Note 0 means use the gdk size */
    int screenheight;
    int lrh_offsetx; /* lower right hand corner x offset */
    int lrh_offsety; /* lower right hand corner y offset */

    /* Flexi stuff */
    char *parent_disp;
    Display *parent_dsp;
    char *parent_auth_file;
    char *parent_temp_auth_file;
    uid_t server_uid;
    GdmConnection *socket_conn;

    int xdmcp_dispnum;

    /* Notification connection */
    int master_notify_fd;  /* write part of the connection */
    int slave_notify_fd; /* read part of the connection */

    /* order in the Xservers file for sessreg, -1 if unset yet */
    int x_servers_order;

    /* The xsession-errors connection */
    int xsession_errors_fd; /* write to the file */
    int session_output_fd; /* read from the session */
    int xsession_errors_bytes;
#define MAX_XSESSION_ERRORS_BYTES (80*2500)  /* maximum number of bytes in
						the ~/.xsession-errors file */
    char *xsession_errors_filename; /* if NULL then there is no .xsession-errors
				       file */

    int chooser_output_fd; /* from the chooser */
    char *chooser_last_line;

    /* Only set in the main daemon as that's the only place that cares */
    GdmLogoutAction logout_action;
    
    char *theme_name;
};

typedef struct _GdmXserver GdmXserver;
struct _GdmXserver {
	char *id;
	char *name;
	char *command;
	gboolean flexible;
	gboolean choosable; /* not implemented yet */
	gboolean chooser; /* instead of greeter, run chooser */
	gboolean handled;
	int priority;
};

typedef struct _GdmIndirectDisplay GdmIndirectDisplay;
struct _GdmIndirectDisplay {
	int id;
#ifdef ENABLE_IPV6
       struct sockaddr_storage* dsp_sa;
       struct in6_addr* chosen_host6;
#else
	struct sockaddr_in* dsp_sa;
#endif
	time_t acctime;
	struct in_addr *chosen_host;
};

/* NOTE: Timeout and max are hardcoded */
typedef struct _GdmForwardQuery GdmForwardQuery;
struct _GdmForwardQuery {
	time_t acctime;
#ifdef ENABLE_IPV6
       struct sockaddr_storage* dsp_sa;
       struct sockaddr_storage* from_sa;
#else
	struct sockaddr_in* dsp_sa;
	struct sockaddr_in* from_sa;
#endif
};
#define GDM_MAX_FORWARD_QUERIES 10
#define GDM_FORWARD_QUERY_TIMEOUT 30

/* some extra XDMCP opcodes that xdm will happily ignore since they'll be
 * the wrong XDMCP version anyway */
#define GDM_XDMCP_PROTOCOL_VERSION 1001
enum {
	GDM_XDMCP_FIRST_OPCODE = 1000, /*just a marker, not an opcode */

	GDM_XDMCP_MANAGED_FORWARD = 1000,
		/* manager (master) -> manager
		 * A packet with MANAGED_FORWARD is sent to the
		 * manager that sent the forward query from the manager to
		 * which forward query was sent.  It indicates that the forward
		 * was fully processed and that the client now has either
		 * a managed session, or has been sent denial, refuse or failed.
		 * (if the denial gets lost then client gets dumped into the
		 * chooser again).  This should be resent a few times
		 * until some (short) timeout or until GOT_MANAGED_FORWARD
		 * is sent.  GDM sends at most 3 packates with 1.5 seconds
		 * between each.
		 *
		 * Argument is ARRAY8 with the address of the originating host */
	GDM_XDMCP_GOT_MANAGED_FORWARD,
		/* manager -> manager (master)
		 * A single packet with GOT_MANAGED_FORWARD is sent to indicate
		 * that we did receive the MANAGED_FORWARD packet.  The argument
		 * must match the MANAGED_FORWARD one or it will just be ignored.
		 *
		 * Argument is ARRAY8 with the address of the originating host */
	GDM_XDMCP_LAST_OPCODE /*just a marker, not an opcode */
};

/* If id == NULL, then get the first X server */
void		gdm_final_cleanup	(void);


/* primitive protocol for controlling the daemon from slave
 * or gdmconfig or whatnot */

/* The ones that pass a <slave pid> must be from a valid slave, and
 * the slave will be sent a SIGUSR2.  Nowdays there is a pipe that is
 * used from inside slaves, so those messages may stop being processed
 * by the fifo at some point perhaps.  */
/* The fifo protocol, used only by gdm internally */
#define GDM_SOP_CHOSEN       "CHOSEN" /* <indirect id> <ip addr> */
#define GDM_SOP_CHOSEN_LOCAL "CHOSEN_LOCAL" /* <slave pid> <hostname> */
#define GDM_SOP_XPID         "XPID" /* <slave pid> <xpid> */
#define GDM_SOP_SESSPID      "SESSPID" /* <slave pid> <sesspid> */
#define GDM_SOP_GREETPID     "GREETPID" /* <slave pid> <greetpid> */
#define GDM_SOP_CHOOSERPID   "CHOOSERPID" /* <slave pid> <chooserpid> */
#define GDM_SOP_LOGGED_IN    "LOGGED_IN" /* <slave pid> <logged_in as int> */
#define GDM_SOP_LOGIN        "LOGIN" /* <slave pid> <username> */
#define GDM_SOP_COOKIE       "COOKIE" /* <slave pid> <cookie> */
#define GDM_SOP_AUTHFILE     "AUTHFILE" /* <slave pid> <authfile> */
#define GDM_SOP_QUERYLOGIN   "QUERYLOGIN" /* <slave pid> <username> */
/* if user already logged in somewhere, the ack response will be
   <display>,<migratable>,<display>,<migratable>,... */
#define GDM_SOP_MIGRATE      "MIGRATE" /* <slave pid> <display> */
#define GDM_SOP_DISP_NUM     "DISP_NUM" /* <slave pid> <display as int> */
/* For Linux only currently */
#define GDM_SOP_VT_NUM       "VT_NUM" /* <slave pid> <vt as int> */
#define GDM_SOP_FLEXI_ERR    "FLEXI_ERR" /* <slave pid> <error num> */
	/* 3 = X failed */
	/* 4 = X too busy */
	/* 5 = Xnest can't connect */
#define GDM_SOP_FLEXI_OK     "FLEXI_OK" /* <slave pid> */
#define GDM_SOP_SOFT_RESTART "SOFT_RESTART" /* no arguments */
#define GDM_SOP_START_NEXT_LOCAL "START_NEXT_LOCAL" /* no arguments */
#define GDM_SOP_HUP_ALL_GREETERS "HUP_ALL_GREETERS" /* no arguments */

/* stop waiting for this and go on with your life, useful with
   the --wait-for-go command line option */
#define GDM_SOP_GO "GO" /* no arguments */

/* sometimes we can't do a syslog so we tell the main daemon */
#define GDM_SOP_SYSLOG "SYSLOG" /* <pid> <type> <message> */

/* write out a sessreg (xdm) compatible Xservers file
 * in the ServAuthDir as <name>.Xservers */
#define GDM_SOP_WRITE_X_SERVERS "WRITE_X_SERVERS" /* <slave pid> */

/* All X servers should be restarted rather then regenerated.  Useful
 * if you have updated the X configuration.  Note that this happens
 * only when the user logs out or when we otherwise would have restarted
 * a server, nothing is done by this command. */
#define GDM_SOP_DIRTY_SERVERS "DIRTY_SERVERS"  /* no arguments */

/* restart all servers that people aren't logged in on.  Maybe you may not
 * want to do this on every change of X server config since this may cause
 * flicker on screen and jumping around on the vt.  Perhaps useful to do
 * by asking the user if they want to do that.  Note that this will not
 * kill any logged in sessions. */
#define GDM_SOP_SOFT_RESTART_SERVERS "SOFT_RESTART_SERVERS"  /* no arguments */
/* Suspend the machine if it is even allowed */
#define GDM_SOP_SUSPEND_MACHINE "SUSPEND_MACHINE"  /* no arguments */
#define GDM_SOP_CHOSEN_THEME "CHOSEN_THEME"  /* <slave pid> <theme name> */

/*Execute custom cmd*/
#define GDM_SOP_CUSTOM_CMD "CUSTOM_CMD"  /* <slave pid> <cmd id> */

/* Start a new standard X flexible server */
#define GDM_SOP_FLEXI_XSERVER "FLEXI_XSERVER" /* no arguments */

/* Notification protocol */
/* keys */
#define GDM_NOTIFY_ALLOW_REMOTE_ROOT "AllowRemoteRoot" /* <true/false as int> */
#define GDM_NOTIFY_ALLOW_ROOT "AllowRoot" /* <true/false as int> */
#define GDM_NOTIFY_ALLOW_REMOTE_AUTOLOGIN "AllowRemoteAutoLogin" /* <true/false as int> */
#define GDM_NOTIFY_SYSTEM_MENU "SystemMenu" /* <true/false as int> */
#define GDM_NOTIFY_CONFIG_AVAILABLE "ConfigAvailable" /* <true/false as int> */
#define GDM_NOTIFY_CHOOSER_BUTTON "ChooserButton" /* <true/false as int> */
#define GDM_NOTIFY_RETRY_DELAY "RetryDelay" /* <seconds> */
#define GDM_NOTIFY_GREETER "Greeter" /* <greeter binary> */
#define GDM_NOTIFY_REMOTE_GREETER "RemoteGreeter" /* <greeter binary> */
#define GDM_NOTIFY_TIMED_LOGIN "TimedLogin" /* <login> */
#define GDM_NOTIFY_TIMED_LOGIN_DELAY "TimedLoginDelay" /* <seconds> */
#define GDM_NOTIFY_TIMED_LOGIN_ENABLE "TimedLoginEnable" /* <true/false as int> */
#define GDM_NOTIFY_DISALLOW_TCP "DisallowTCP" /* <true/false as int> */
#define GDM_NOTIFY_SOUND_ON_LOGIN_FILE "SoundOnLoginFile" /* <sound file> */
#define GDM_NOTIFY_SOUND_ON_LOGIN_SUCCESS_FILE "SoundOnLoginSuccessFile" /* <sound file> */
#define GDM_NOTIFY_SOUND_ON_LOGIN_FAILURE_FILE "SoundOnLoginFailureFile" /* <sound file> */
#define GDM_NOTIFY_ADD_GTK_MODULES "AddGtkModules" /* <true/false as int> */
#define GDM_NOTIFY_GTK_MODULES_LIST "GtkModulesList" /* <modules list> */
#define GDM_NOTIFY_CUSTOM_CMD_TEMPLATE "CustomCommand" /* <custom command path> */

/* commands, seel GDM_SLAVE_NOTIFY_COMMAND */
#define GDM_NOTIFY_DIRTY_SERVERS "DIRTY_SERVERS"
#define GDM_NOTIFY_SOFT_RESTART_SERVERS "SOFT_RESTART_SERVERS"
#define GDM_NOTIFY_GO "GO"
#define GDM_NOTIFY_TWIDDLE_POINTER "TWIDDLE_POINTER"

/* Ack for a slave message */
/* Note that an extra response can follow an 'ack' */
#define GDM_SLAVE_NOTIFY_ACK 'A'
/* Update this key */
#define GDM_SLAVE_NOTIFY_KEY '!'
/* notify a command */
#define GDM_SLAVE_NOTIFY_COMMAND '#'

/*
 * Maximum number of messages allowed over the sockets protocol.  This
 * is set to 80 since the gdmlogin/gdmgreeter programs have ~60 config
 * values that are pulled over the socket connection so it allows them
 * all to be grabbed in one pull.
 */
#define GDM_SUP_MAX_MESSAGES 80
#define GDM_SUP_SOCKET "/tmp/.gdm_socket"

/*
 * The user socket protocol.  Each command is given on a separate line
 *
 * A user should first send a VERSION\n after connecting and only do
 * anything else if gdm responds with the correct response.  The version
 * is the gdm version and not a "protocol" revision, so you can't check
 * against a single version but check if the version is higher then some
 * value.
 *
 * You can only send a few commands at a time, so if you keep getting error
 * 200 try opening a new socket for every command you send.
 */
/* The user protocol, using /tmp/.gdm_socket */

#define GDM_SUP_VERSION "VERSION" /* no arguments */
/* VERSION: Query GDM version
 * Supported since: 2.2.4.0
 * Arguments: None
 * Answers:
 *   GDM <gdm version>
 *   ERROR <err number> <english error description>
 *      200 = Too many messages
 *      999 = Unknown error
 */
#define GDM_SUP_AUTH_LOCAL "AUTH_LOCAL" /* <xauth cookie> */
/* AUTH_LOCAL: Setup this connection as authenticated for FLEXI_SERVER.
 *             Because all full blown (non-Xnest) displays can be started
 *             only from users logged in locally, and here gdm assumes
 *             only users logged in from gdm.  They must pass the xauth
 *             MIT-MAGIC-COOKIE-1 that they were passed before the
 *             connection is authenticated.
 * Note:       The AUTH LOCAL command requires the --authenticate option,
 *             although only FLEXI XSERVER uses this currently.
 * Note:       Since 2.6.0.6 you can also use a global
 *             <ServAuthDir>/.cookie, which works for all authentication
 *             except for SET_LOGOUT_ACTION and QUERY_LOGOUT_ACTION
 *             and SET_SAFE_LOGOUT_ACTION which require a logged in
 *             display.
 * Supported since: 2.2.4.0
 * Arguments: <xauth cookie>
 *   <xauth cookie> is in hex form with no 0x prefix
 * Answers:
 *   OK
 *   ERROR <err number> <english error description>
 *      0 = Not implemented
 *      100 = Not authenticated
 *      200 = Too many messages
 *      999 = Unknown error
 */
#define GDM_SUP_FLEXI_XSERVER "FLEXI_XSERVER" /* <xserver type> */
/* FLEXI_XSERVER: Start a new X flexible display.  Only supported on
 *                connection that passed AUTH_LOCAL
 * Supported since: 2.2.4.0
 * Arguments: <xserver type>
 *   If no arguments, starts the standard X server
 * Answers:
 *   OK <display>
 *   ERROR <err number> <english error description>
 *      0 = Not implemented
 *      1 = No more flexi servers
 *      2 = Startup errors
 *      3 = X failed
 *      4 = X too busy
 *      6 = No server binary
 *      100 = Not authenticated
 *      200 = Too many messages
 *      999 = Unknown error
 */
#define GDM_SUP_FLEXI_XNEST  "FLEXI_XNEST" /* <display> <uid> <xauth cookie> <xauth file> */
/* FLEXI_XNEXT: Start a new flexible Xnest display.
 * Note:        Supported on older versions from 2.2.4.0, later
 *              2.2.4.2, but since 2.3.90.4 you must supply 4 
 *              arguments or ERROR 100 will be returned.  This
 *              will start Xnest using the XAUTHORITY file
 *              supplied and as the uid same as the owner of
 *              that file (and same as you supply).  You must
 *              also supply the cookie as the third argument
 *              for this display, to prove that you indeed are
 *              this user.  Also this file must be readable
 *              ONLY by this user, that is have a mode of 0600.
 *              If this all is not met, ERROR 100 is returned.
 * Note:        The cookie should be the MIT-MAGIC-COOKIE-1,
 *              the first one gdm can find in the XAUTHORITY
 *              file for this display.  If that's not what you
 *              use you should generate one first.  The cookie
 *              should be in hex form.
 * Supported since: 2.3.90.4
 * Arguments: <display to run on> <uid of requesting user>
 *            <xauth cookie for the display> <xauth file>
 * Answers:
 *   OK <display>
 *   ERROR <err number> <english error description>
 *      0 = Not implemented
 *      1 = No more flexi servers
 *      2 = Startup errors
 *      3 = X failed
 *      4 = X too busy
 *      5 = Xnest can't connect
 *      6 = No server binary
 *      100 = Not authenticated
 *      200 = Too many messages
 *      999 = Unknown error
 */
#define GDM_SUP_ADD_DYNAMIC_DISPLAY	"ADD_DYNAMIC_DISPLAY" 
/*
 * ADD_DYNAMIC_DISPLAY: Create a new server definition that will
 *                      run on the specified display leaving it
 *                      in DISPLAY_CONFIG state.
 * Supported since: 2.8.0.0
 * Arguments: <display to run on>=<server>
 *   Where <server> is either a configuration named in the
 *   GDM configuration a literal command name.
 * Answers:
 *  OK
 *  ERROR
 *     0 = Not implemented
 *     2 = Existing display
 *     3 = No server string
 *     4 = Display startup failure
 *     100 = Not authenticated
 *     200 - Dynamic Displays not allowed
 *     999 = Unknown error
 */
#define GDM_SUP_RELEASE_DYNAMIC_DISPLAYS	"RELEASE_DYNAMIC_DISPLAYS"
/*
 * RELEASE_DYNAMIC_DISPLAYS: Release and begin managing dynamic displays
 *                           currently in DISPLAY_CONFIG state
 * Supported since: 2.8.0.0
 * Arguments: <display to release>
 * Answers:
 *  OK
 *  ERROR
 *     0 = Not implemented
 *     1 = Bad display number
 *     100 = Not authenticated
 *     200 = Dynamic Displays not allowed
 *     999 = Unknown error
 */
#define GDM_SUP_REMOVE_DYNAMIC_DISPLAY	"REMOVE_DYNAMIC_DISPLAY" 
/*
 * REMOVE_DYNAMIC_DISPLAY: Remove a dynamic display, killing the server
 *                         and purging the display configuration
 * Supported since: 2.8.0.0
 * Arguments: <display to remove>
 * Answers:
 *  OK
 *  ERROR
 *     0 = Not implemented
 *     1 = Bad display number
 *     100 = Not authenticated
 *     200 = Dynamic Displays not allowed
 *     999 = Unknown error
 */
#define GDM_SUP_ATTACHED_SERVERS "ATTACHED_SERVERS" /* None */
#define GDM_SUP_CONSOLE_SERVERS  "CONSOLE_SERVERS"  /* None */
/* ATTACHED_SERVERS: List all attached displays.  Doesn't list XDMCP
 *                   and xnest non-attached displays.
 * Note:             This command used to be named CONSOLE_SERVERS,
 *                   which is still recognized for backwards
 *                   compatibility.  The optional pattern argument
 *                   is supported as of version 2.8.0.0.
 * Supported since: 2.2.4.0
 * Arguments: <pattern> (optional)
 *   With no argument, all dynamic displays are returned. The optional
 *   <pattern> is a string that may contain glob characters '*', '?', and
 *   '[]'. Only displays that match the pattern will be returned.
 * Answers:
 *   OK <server>;<server>;...
 *
 *   <server> is <display>,<logged in user>,<vt or xnest display>
 *
 *   <logged in user> can be empty in case no one logged in yet,
 *   and <vt> can be -1 if it's not known or not supported (on non-Linux
 *   for example).  If the display is an xnest display and is an attached one
 *   (that is, it is an xnest inside another attached display) it is listed
 *   and instead of vt, it lists the parent display in standard form.
 *
 *   ERROR <err number> <english error description>
 *      0 = Not implemented
 *      200 = Too many messages
 *      999 = Unknown error
 */
#define GDM_SUP_ALL_SERVERS  "ALL_SERVERS" /* None */
/* ALL_SERVERS: List all displays, including attached, remote, xnest.
 *              This can for example be useful to figure out if
 *              the display you are on is managed by the gdm daemon,
 *              by seeing if it is in the list.  It is also somewhat
 *              like the 'w' command but for graphical sessions.
 * Supported since: 2.4.2.96
 * Arguments: None
 * Answers:
 *   OK <server>;<server>;...
 *
 *   <server> is <display>,<logged in user>
 *
 *   <logged in user> can be empty in case no one logged in yet
 *
 *   ERROR <err number> <english error description>
 *      0 = Not implemented
 *      200 = Too many messages
 *      999 = Unknown error
 */
#define GDM_SUP_GET_SERVER_LIST "GET_SERVER_LIST" /* None */
/* GET_SERVER_LIST:  Get a list of the server sections from
 *                   the configuration file. 
 * Supported since: 2.13.0.4
 * Arguments: None 
 * Answers:
 *   OK <value>;<value>;...
 *   ERROR <err number> <english error description>
 *      0 = Not implemented
 *      1 = No servers found
 *      200 = Too many messages
 *      999 = Unknown error
 */
#define GDM_SUP_GET_SERVER_DETAILS "GET_SERVER_DETAILS" /* <server> <key> */
/* GET_SERVER_DETAILS:  Get detail information for a specific server.
 * Supported since: 2.13.0.4
 * Arguments: <server> <key>
 *   Key values include:
 *     ID        - Returns the server id
 *     NAME      - Returns the server name
 *     COMMAND   - Returns the server command
 *     FLEXIBLE  - Returns "true" if flexible, "false" otherwise
 *     CHOOSABLE - Returns "true" if choosable, "false" otherwise
 *     HANDLED   - Returns "true" if handled, "false" otherwise
 *     CHOOSER   - Returns "true" if chooser, "false" otherwise
 *     PRIORITY  - Returns process priority
 * Answers: 
 *   OK <value>
 *   ERROR <err number> <english error description>
 *      0 = Not implemented
 *      1 = Server not found
 *      2 = Key not valid
 *      50 = Unsupported key
 *      200 = Too many messages
 *      999 = Unknown error
 */
#define GDM_SUP_GET_CONFIG "GET_CONFIG" /* <key> */
/* GET_CONFIG:  Get configuration value for key.  Useful so
 *              that other applications can request configuration
 *              information from GDM.  Any key defined as GDM_KEY_*
 *              in gdm.h is supported.  Starting with version 2.13.0.2
 *              translated keys (such as "greeter/GdmWelcome[cs]" are
 *              supported via GET_CONFIG.  Also starting with version
 *              2.13.0.2 it is no longer necessary to include the
 *              default value (i.e. you can use key "greeter/IncludeAll"
 *              instead of having to use "greeter/IncludeAll=false".
 *              Starting with version 2.14.4, GDM supports per-display
 *              configuration (for GUI slave clients only) and accepts
 *              the display argument to retrieve per-display value (if
 *              any.
 * Supported since: 2.6.0.9
 * Arguments: <key> [<display>]
 * Answers:
 *   OK <value>
 *   ERROR <err number> <english error description>
 *      0 = Not implemented
 *      50 = Unsupported key
 *      200 = Too many messages
 *      999 = Unknown error
 */
#define GDM_SUP_GET_CONFIG_FILE  "GET_CONFIG_FILE" /* None */
/* GET_CONFIG_FILE: Get defaults config file location being used by
 #                  the daemon.   If the GDM daemon was started
 *                  with the --config option, it will return
 *                  the value passed in via that argument.
 * Supported since: 2.8.0.2
 * Arguments: None
 * Answers:
 *   OK <full path to GDM configuration file>
 *   ERROR <err number> <english error description>
 *      0 = Not implemented
 *      200 = Too many messages
 *      999 = Unknown error
 */
#define GDM_SUP_GET_CUSTOM_CONFIG_FILE  "GET_CUSTOM_CONFIG_FILE" /* None */
/* GET_CONFIG_FILE: Get custom config file location being used by
 #                  the daemon. 
 * Supported since: 2.14.0.0
 * Arguments: None
 * Answers:
 *   OK <full path to GDM custom configuration file>
 *   ERROR <err number> <english error description>
 *      0 = Not implemented
 *      1 = File not found
 *      200 = Too many messages
 *      999 = Unknown error
 */
#define GDM_SUP_UPDATE_CONFIG "UPDATE_CONFIG" /* <key> */
/* UPDATE_CONFIG: Tell the daemon to re-read a key from the
 *                GDM configuration file.   Any user can request
 *                that values are re-read but the daemon will
 *                only do so if the file has been modified
 *                since GDM first read the file.  Only users
 *                who can change the GDM configuration file
 *                (normally writable only by the root user) can
 *                actually modify the GDM configuration.  This
 *                command is useful to cause the GDM to update
 *                itself to recognize a change made to the GDM
 *                configuration file by the root user.
 *
 *                Starting with version 2.13.0.0, all GDM keys are
 *                supported except for the following:
 *
 *                    daemon/PidFile
 *                    daemon/ConsoleNotify
 *                    daemon/User
 *                    daemon/Group
 *                    daemon/LogDir
 *                    daemon/ServAuthDir
 *                    daemon/UserAuthDir
 *                    daemon/UserAuthFile
 *                    daemon/UserAuthFBDir
 *
 *                GDM also supports the following Psuedokeys:
 *
 *                xdmcp/PARAMETERS (2.3.90.2) updates the following:
 *                    xdmcp/MaxPending
 *                    xdmcp/MaxSessions
 *                    xdmcp/MaxWait
 *                    xdmcp/DisplaysPerHost
 *                    xdmcp/HonorIndirect
 *                    xdmcp/MaxPendingIndirect
 *                    xdmcp/MaxWaitIndirect
 *                    xdmcp/PingIntervalSeconds (only affects new connections)
 *
 *                 xservers/PARAMETERS (2.13.0.4) updates the following:
 *                    all [server-foo] sections.
 *
 *                 Supported keys for previous versions of GDM:
 *
 *                    security/AllowRoot (2.3.90.2)
 *                    security/AllowRemoteRoot (2.3.90.2)
 *                    security/AllowRemoteAutoLogin (2.3.90.2)
 *                    security/RetryDelay (2.3.90.2)
 *                    security/DisallowTCP (2.4.2.0)
 *                    daemon/Greeter (2.3.90.2)
 *                    daemon/RemoteGreeter (2.3.90.2)
 *                    xdmcp/Enable (2.3.90.2)
 *                    xdmcp/Port (2.3.90.2)
 *                    daemon/TimedLogin (2.3.90.3)
 *                    daemon/TimedLoginEnable (2.3.90.3)
 *                    daemon/TimedLoginDelay (2.3.90.3)
 *                    greeter/SystemMenu (2.3.90.3)
 *                    greeter/ConfigAvailable (2.3.90.3)
 *                    greeter/ChooserButton (2.4.2.0)
 *                    greeter/SoundOnLoginFile (2.5.90.0)
 *                    daemon/AddGtkModules (2.5.90.0)
 *                    daemon/GtkModulesList (2.5.90.0)
 * Supported since: 2.3.90.2
 * Arguments: <key>
 *   <key> is just the base part of the key such as "security/AllowRemoteRoot"
 * Answers:
 *   OK
 *   ERROR <err number> <english error description>
 *      0 = Not implemented
 *      50 = Unsupported key
 *      200 = Too many messages
 *      999 = Unknown error
 */
#define GDM_SUP_GREETERPIDS  "GREETERPIDS" /* None */
/* GREETERPIDS: List all greeter pids so that one can send HUP
 *              to them for config rereading.  Of course one
 *              must be root to do that.
 * Supported since: 2.3.90.2
 * Arguments: None
 * Answers:
 *   OK <pid>;<pid>;...
 *   ERROR <err number> <english error description>
 *      0 = Not implemented
 *      200 = Too many messages
 *      999 = Unknown error
 */
#define GDM_SUP_QUERY_LOGOUT_ACTION "QUERY_LOGOUT_ACTION" /* None */
/* QUERY_LOGOUT_ACTION: Query which logout actions are possible
 *                      Only supported on connections that passed
 *                      AUTH_LOCAL.
 * Supported since: 2.5.90.0
 * Answers:
 *   OK <action>;<action>;...
 *      Where action is one of HALT, REBOOT, SUSPEND or CUSTOM_CMDX (where X in [0,GDM_CUSTOM_COMMAND_MAX)).
 *      An empty list can also be returned if no action is possible.  A '!' is appended
 *      to an action if it was already set with SET_LOGOUT_ACTION or
 *      SET_SAFE_LOGOUT_ACTION.  Note that SET_LOGOUT_ACTION has precedence
 *      over SET_SAFE_LOGOUT_ACTION.
 *   ERROR <err number> <english error description>
 *      0 = Not implemented
 *      100 = Not authenticated
 *      200 = Too many messages
 *      999 = Unknown error
 */
#define GDM_SUP_SET_LOGOUT_ACTION "SET_LOGOUT_ACTION" /* <action> */
/* SET_LOGOUT_ACTION: Tell the daemon to halt/restart/suspend after
 *                    slave process exits.  Only supported on
 *                    connections that passed AUTH_LOCAL.
 * Supported since: 2.5.90.0
 * Arguments: <action>
 *   NONE           Set exit action to 'none'
 *   HALT           Set exit action to 'halt'
 *   REBOOT         Set exit action to 'reboot'
 *   SUSPEND        Set exit action to 'suspend'
 *   CUSTOM_CMDX    Set exit action to 'custom command X' where where X in [0,GDM_CUSTOM_COMMAND_MAX)
 * Answers:
 *   OK
 *   ERROR <err number> <english error description>
 *      0 = Not implemented
 *      7 = Unknown logout action, or not available
 *      100 = Not authenticated
 *      200 = Too many messages
 *      999 = Unknown error
 */
#define GDM_SUP_SET_SAFE_LOGOUT_ACTION "SET_SAFE_LOGOUT_ACTION" /* <action> */
/* SET_SAFE_LOGOUT_ACTION: Tell the daemon to halt/restart/suspend
 *                         after everybody logs out.  If only one
 *                         person logs out, then this is obviously
 *                         the same as the SET_LOGOUT_ACTION.  Note
 *                         that SET_LOGOUT_ACTION has precendence
 *                         over SET_SAFE_LOGOUT_ACTION if it is set
 *                         to something other then NONE.  If no one
 *                         is logged in, then the action takes effect
 *                         immedeately.  Only supported on connections
 *                         that passed AUTH_LOCAL.
 * Supported since: 2.5.90.0
 * Arguments: <action>
 *   NONE           Set exit action to 'none'
 *   HALT           Set exit action to 'halt'
 *   REBOOT         Set exit action to 'reboot'
 *   SUSPEND        Set exit action to 'suspend'
 *   CUSTOM_CMDX    Set exit action to 'custom command X' where where X in [0,GDM_CUSTOM_COMMAND_MAX)
 *
 * Answers:
 *   OK
 *   ERROR <err number> <english error description>
 *      0 = Not implemented
 *      7 = Unknown logout action, or not available
 *      100 = Not authenticated
 *      200 = Too many messages
 *      999 = Unknown error
 */
#define GDM_SUP_LOGOUT_ACTION_NONE	          "NONE"
#define GDM_SUP_LOGOUT_ACTION_HALT	          "HALT"
#define GDM_SUP_LOGOUT_ACTION_REBOOT	          "REBOOT"
#define GDM_SUP_LOGOUT_ACTION_SUSPEND	          "SUSPEND"
#define GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE "CUSTOM_CMD"
/*
 */
#define GDM_SUP_QUERY_VT "QUERY_VT" /* None */
/* QUERY_VT:  Ask the daemon about which VT we are currently on.
 *            This is useful for logins which don't own
 *            /dev/console but are still console logins.  Only
 *            supported on Linux currently, other places will
 *            just get ERROR 8.  This is also the way to query
 *            if VT support is available in the daemon in the
 *            first place.  Only supported on connections that
 *            passed AUTH_LOCAL.
 * Supported since: 2.5.90.0
 * Arguments: None
 * Answers:
 *   OK <vt number>
 *   ERROR <err number> <english error description>
 *      0 = Not implemented
 *      8 = Virtual terminals not supported
 *      100 = Not authenticated
 *      200 = Too many messages
 *      999 = Unknown error
 */
#define GDM_SUP_SET_VT "SET_VT" /* <vt> */
/* SET_VT:  Change to the specified virtual terminal.
 *          This is useful for logins which don't own /dev/console
 *          but are still console logins.  Only supported on Linux
 *          currently, other places will just get ERROR 8.
 *          Only supported on connections that passed AUTH_LOCAL.
 * Supported since: 2.5.90.0
 * Arguments: None
 * Answers:
 *   OK
 *   ERROR <err number> <english error description>
 *      0 = Not implemented
 *      8 = Virtual terminals not supported
 *      9 = Invalid virtual terminal number
 *      100 = Not authenticated
 *      200 = Too many messages
 *      999 = Unknown error
 */
#define GDM_SUP_SERVER_BUSY "SERVER_BUSY" /* None */
/* SERVER_BUSY:  Returns true if half or more of the daemon's sockets are
 *               busy, false otherwise.  Used by slave programs which want
 *               to ensure they do not overhwelm the server.
 * Supported since: 2.13.0.8
 * Arguments: None 
 * Answers:
 *   OK <value>
 *   ERROR <err number> <english error description>
 *      0 = Not implemented
 *      200 = Too many messages
 *      999 = Unknown error
 */
#define GDM_SUP_GET_SERVER_DETAILS "GET_SERVER_DETAILS" /* <server> <key> */
#define GDM_SUP_CLOSE        "CLOSE" /* None */
/* CLOSE: Close sockets connection
 * Supported since: 2.2.4.0
 * Arguments: None
 * Answers: None
 */

/* User flags for the SUP protocol */
enum {
	GDM_SUP_FLAG_AUTHENTICATED = 0x1, /* authenticated as a local user,
					  * from a local display we started */
	GDM_SUP_FLAG_AUTH_GLOBAL = 0x2 /* authenticated with global cookie */
};

/* Macros to check authentication level */
#define GDM_CONN_AUTHENTICATED(conn) \
	((gdm_connection_get_user_flags (conn) & GDM_SUP_FLAG_AUTHENTICATED) || \
	 (gdm_connection_get_user_flags (conn) & GDM_SUP_FLAG_AUTH_GLOBAL))

#define GDM_CONN_AUTH_GLOBAL(conn) \
	 (gdm_connection_get_user_flags (conn) & GDM_SUP_FLAG_AUTH_GLOBAL)


#define NEVER_FAILS_seteuid(uid) \
	{ int r = 0; \
	  if (geteuid () != uid) \
	    r = seteuid (uid); \
	  if G_UNLIKELY (r != 0) \
        gdm_fail ("GDM file %s: line %d (%s): Cannot run seteuid to %d: %s", \
		  __FILE__,						\
		  __LINE__,						\
		  __PRETTY_FUNCTION__,					\
                  (int)uid,						\
		  strerror (errno));			}
#define NEVER_FAILS_setegid(gid) \
	{ int r = 0; \
	  if (getegid () != gid) \
	    r = setegid (gid); \
	  if G_UNLIKELY (r != 0) \
        gdm_fail ("GDM file %s: line %d (%s): Cannot run setegid to %d: %s", \
		  __FILE__,						\
		  __LINE__,						\
		  __PRETTY_FUNCTION__,					\
                  (int)gid,						\
		  strerror (errno));			}

/* first goes to euid-root and then sets the egid and euid, to make sure
 * this succeeds */
#define NEVER_FAILS_root_set_euid_egid(uid,gid) \
	{ NEVER_FAILS_seteuid (0); \
	  NEVER_FAILS_setegid (gid); \
	  if (uid != 0) { NEVER_FAILS_seteuid (uid); } }

#endif /* GDM_H */

/* EOF */