6 #include <sys/socket.h>
10 #include <X11/Xauth.h>
24 #define GDM_PROTOCOL_SOCKET_PATH1 "/var/run/gdm_socket"
25 #define GDM_PROTOCOL_SOCKET_PATH2 "/tmp/.gdm_socket"
27 #define GDM_PROTOCOL_MSG_CLOSE "CLOSE"
28 #define GDM_PROTOCOL_MSG_VERSION "VERSION"
29 #define GDM_PROTOCOL_MSG_AUTHENTICATE "AUTH_LOCAL"
30 #define GDM_PROTOCOL_MSG_QUERY_ACTION "QUERY_LOGOUT_ACTION"
31 #define GDM_PROTOCOL_MSG_SET_ACTION "SET_SAFE_LOGOUT_ACTION"
32 #define GDM_PROTOCOL_MSG_FLEXI_XSERVER "FLEXI_XSERVER"
34 #define GDM_ACTION_STR_NONE GDM_PROTOCOL_MSG_SET_ACTION" NONE"
35 #define GDM_ACTION_STR_SHUTDOWN GDM_PROTOCOL_MSG_SET_ACTION" HALT"
36 #define GDM_ACTION_STR_REBOOT GDM_PROTOCOL_MSG_SET_ACTION" REBOOT"
37 #define GDM_ACTION_STR_SUSPEND GDM_PROTOCOL_MSG_SET_ACTION" SUSPEND"
39 #define GDM_MIT_MAGIC_COOKIE_LEN 16
43 static void gdm_disconnect()
50 static char* get_display_number(void)
56 display_name
= XDisplayName(NULL
);
58 p
= strchr(display_name
, ':');
60 return g_strdup ("0");
62 while (*p
== ':') p
++;
64 retval
= g_strdup (p
);
66 p
= strchr (retval
, '.');
73 static char* gdm_send_protocol_msg (const char *msg
)
80 p
= g_strconcat(msg
, "\n", NULL
);
81 if (write (fd
, p
, strlen(p
)) < 0) {
84 g_warning ("Failed to send message to GDM: %s",
92 while ((len
= read(fd
, buf
, sizeof(buf
) - 1)) > 0) {
96 retval
= g_string_new(buf
);
98 retval
= g_string_append(retval
, buf
);
100 if ((p
= strchr(retval
->str
, '\n')))
106 return retval
? g_string_free(retval
, FALSE
) : NULL
;
109 static gboolean
gdm_authenticate()
113 const char *xau_path
;
114 char *display_number
;
117 if (!(xau_path
= XauFileName()))
120 if (!(f
= fopen(xau_path
, "r")))
124 display_number
= get_display_number();
126 while ((xau
= XauReadAuth(f
))) {
127 char buffer
[40]; /* 2*16 == 32, so 40 is enough */
132 if (xau
->family
!= FamilyLocal
||
133 strncmp (xau
->number
, display_number
, xau
->number_length
) ||
134 strncmp (xau
->name
, "MIT-MAGIC-COOKIE-1", xau
->name_length
) ||
135 xau
->data_length
!= GDM_MIT_MAGIC_COOKIE_LEN
)
141 for (i
= 0; i
< GDM_MIT_MAGIC_COOKIE_LEN
; i
++)
142 g_snprintf(buffer
+ 2*i
, 3, "%02x", (guint
)(guchar
)xau
->data
[i
]);
146 msg
= g_strdup_printf(GDM_PROTOCOL_MSG_AUTHENTICATE
" %s", buffer
);
147 response
= gdm_send_protocol_msg(msg
);
150 if (response
&& !strcmp(response
, "OK")) {
151 /*auth_cookie = g_strdup(buffer);*/
164 static gboolean
gdm_connect()
166 struct sockaddr_un addr
;
171 fd
= socket(AF_UNIX
, SOCK_STREAM
, 0);
173 g_warning("Failed to create GDM socket: %s", g_strerror (errno
));
178 if (g_file_test(GDM_PROTOCOL_SOCKET_PATH1
, G_FILE_TEST_EXISTS
))
179 strcpy(addr
.sun_path
, GDM_PROTOCOL_SOCKET_PATH1
);
181 strcpy(addr
.sun_path
, GDM_PROTOCOL_SOCKET_PATH2
);
183 addr
.sun_family
= AF_UNIX
;
185 if (connect(fd
, (struct sockaddr
*) &addr
, sizeof (addr
)) < 0) {
186 g_warning("Failed to establish a connection with GDM: %s",
192 response
= gdm_send_protocol_msg(GDM_PROTOCOL_MSG_VERSION
);
193 if (!response
|| strncmp(response
, "GDM ", strlen("GDM ") != 0)) {
196 g_warning("Failed to get protocol version from GDM");
202 if (!gdm_authenticate()) {
203 g_warning("Failed to authenticate with GDM");
211 int main(int argc
, char **argv
)
216 for (i
= 1; i
< argc
; ++i
) {
217 if (!strcmp(argv
[i
], "--help")) {
221 if (!strcmp(argv
[i
], "--none")) {
225 if (!strcmp(argv
[i
], "--shutdown")) {
229 if (!strcmp(argv
[i
], "--reboot")) {
233 if (!strcmp(argv
[i
], "--suspend")) {
237 if (!strcmp(argv
[i
], "--switch-user")) {
244 printf("Usage: gdm-control ACTION\n\n");
245 printf("Actions:\n");
246 printf(" --help Display this help and exit\n");
247 printf(" --none Do nothing special when the current session ends\n");
248 printf(" --shutdown Shutdown the computer when the current session ends\n");
249 printf(" --reboot Reboot the computer when the current session ends\n");
250 printf(" --suspend Suspend the computer when the current session ends\n");
251 printf(" --switch-user Log in as a new user (this works immediately)\n\n");
257 const char *action_string
;
259 d
= XDisplayName(NULL
);
262 "Unable to find the X display specified by the DISPLAY "
263 "environment variable. Ensure that it is set correctly.");
269 action_string
= GDM_ACTION_STR_NONE
;
272 action_string
= GDM_ACTION_STR_SHUTDOWN
;
275 action_string
= GDM_ACTION_STR_REBOOT
;
278 action_string
= GDM_ACTION_STR_SUSPEND
;
281 action_string
= GDM_PROTOCOL_MSG_FLEXI_XSERVER
;
288 response
= gdm_send_protocol_msg(action_string
);