Adding upstream version 0.4.1.
[debian/lxdm.git] / src / ui.c
1 /*
2 * ui.c - basic ui of lxdm
3 *
4 * Copyright 2009 dgod <dgod.osa@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 * MA 02110-1301, USA.
20 */
21
22
23 #include <X11/Xlib.h>
24
25 #include <string.h>
26 #include <poll.h>
27 #include <grp.h>
28 #include <unistd.h>
29 #include <ctype.h>
30 #include <signal.h>
31 #include <errno.h>
32
33 #include <sys/wait.h>
34
35 #include "lxdm.h"
36 #include "lxcom.h"
37
38 static pid_t greeter = -1;
39 static int greeter_pipe[2];
40 static GIOChannel *greeter_io;
41 static guint io_id;
42 static int user;
43 static gboolean first=TRUE;
44
45 static void xwrite(int fd,const void *buf,size_t size)
46 {
47 int ret;
48 do{
49 ret=write(fd,buf,size);
50 }while(ret==-1 && errno==EINTR);
51 }
52
53 static void ui_reset(void)
54 {
55 xwrite(greeter_pipe[0], "reset\n", 6);
56 }
57
58 void ui_drop(void)
59 {
60 /* if greeter, do quit */
61 if( greeter > 0 )
62 {
63 lxcom_del_child_watch(greeter);
64 xwrite(greeter_pipe[0], "exit\n", 5);
65 g_source_remove(io_id);
66 io_id = 0;
67 g_io_channel_unref(greeter_io);
68 greeter_io = NULL;
69 close(greeter_pipe[1]);
70 close(greeter_pipe[0]);
71 waitpid(greeter, 0, 0) ;
72 greeter=-1;
73 user=-1;
74 }
75 if(io_id>0)
76 {
77 g_source_remove(io_id);
78 io_id = 0;
79 g_io_channel_unref(greeter_io);
80 greeter_io = NULL;
81 close(greeter_pipe[1]);
82 close(greeter_pipe[0]);
83 }
84 }
85
86 static void greeter_setup(void *userdata)
87 {
88 struct passwd *pw=userdata;
89 if(!pw)
90 {
91 return;
92 }
93 initgroups(pw->pw_name, pw->pw_gid);
94 setgid(pw->pw_gid);
95 setuid(pw->pw_uid);
96 }
97
98 static gchar *greeter_param(char *str, char *name)
99 {
100 char *temp, *p;
101 char ret[128];
102 int i;
103 temp = g_strdup_printf(" %s=", name);
104 p = strstr(str, temp);
105 if( !p )
106 {
107 g_free(temp);
108 return NULL;
109 }
110 p += strlen(temp);
111 g_free(temp);
112 for( i = 0; i < 127; i++ )
113 {
114 if( !p[i] || isspace(p[i]) )
115 break;
116 ret[i] = p[i];
117 }
118 ret[i] = 0;
119 if(!strcmp(name,"pass"))
120 {
121 gsize outlen;
122 temp=(char*)g_base64_decode(ret,&outlen);
123 if(!temp) return NULL;
124 p=g_malloc(outlen+1);
125 memcpy(p,temp,outlen);
126 p[outlen]=0;
127 g_free(temp);
128 return p;
129 }
130 return g_strdup(ret);
131 }
132
133 static gboolean on_greeter_input(GIOChannel *source, GIOCondition condition, gpointer data)
134 {
135 GIOStatus ret;
136 char *str;
137
138 if( !(G_IO_IN & condition) )
139 return FALSE;
140 ret = g_io_channel_read_line(source, &str, NULL, NULL, NULL);
141 if( ret != G_IO_STATUS_NORMAL )
142 return FALSE;
143
144 if( !strncmp(str, "reboot", 6) )
145 lxdm_do_reboot();
146 else if( !strncmp(str, "shutdown", 6) )
147 lxdm_do_shutdown();
148 else if( !strncmp(str, "log ", 4) )
149 g_message(str + 4);
150 else if( !strncmp(str, "login ", 6) )
151 {
152 char *user = greeter_param(str, "user");
153 char *pass = greeter_param(str, "pass");
154 char *session = greeter_param(str, "session");
155 char *lang = greeter_param(str, "lang");
156 if( user && pass )
157 {
158 struct passwd *pw;
159 int ret = lxdm_auth_user(user, pass, &pw);
160 if( AUTH_SUCCESS == ret && pw != NULL )
161 {
162 ui_drop();
163 lxdm_do_login(pw, session, lang,NULL);
164 }
165 else
166 xwrite(greeter_pipe[0], "reset\n", 6);
167 }
168 g_free(user);
169 g_free(pass);
170 g_free(session);
171 g_free(lang);
172 }
173 else if(!strncmp(str, "autologin ", 10))
174 {
175 char *user=g_key_file_get_string(config,"base","autologin",NULL);
176 char *pass=g_key_file_get_string(config,"base","password",NULL);
177 char *session = greeter_param(str, "session");
178 char *lang = greeter_param(str, "lang");
179
180 if(user)
181 {
182 struct passwd *pw;
183 int ret = lxdm_auth_user(user, pass, &pw);
184 if( AUTH_SUCCESS == ret && pw != NULL )
185 {
186 ui_drop();
187 lxdm_do_login(pw, session, lang,NULL);
188 }
189 else
190 {
191 ui_reset();
192 }
193 }
194 else
195 {
196 ui_reset();
197 }
198
199 g_free(user);
200 g_free(pass);
201 g_free(session);
202 g_free(lang);
203 }
204 g_free(str);
205 return TRUE;
206 }
207
208 static void on_greeter_exit(void *data,int pid, int status)
209 {
210 if( pid != greeter )
211 return;
212 greeter = -1;
213 }
214
215 int ui_greeter_user(void)
216 {
217 return user;
218 }
219
220 void ui_prepare(void)
221 {
222 char *p;
223
224 if(greeter>0)
225 return;
226
227 /* if find greeter, run it */
228 p = g_key_file_get_string(config, "base", "greeter", NULL);
229 if( p && p[0] )
230 {
231 char *argv[3]={p,NULL,NULL};
232 gboolean ret;
233 struct passwd *pw;
234 if(first)
235 {
236 char *t=g_key_file_get_string(config,"base","autologin",NULL);
237 if(t && !strchr(t,' '))
238 argv[1]="--auto-login";
239 g_free(t);
240 first=FALSE;
241 }
242 pw=getpwnam("lxdm");endpwent();
243 ret = g_spawn_async_with_pipes(NULL, argv, NULL,
244 G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,greeter_setup, pw,
245 &greeter, greeter_pipe + 0, greeter_pipe + 1, NULL, NULL);
246 if( ret == TRUE )
247 {
248 g_free(p);
249 greeter_io = g_io_channel_unix_new(greeter_pipe[1]);
250 io_id = g_io_add_watch(greeter_io, G_IO_IN | G_IO_HUP | G_IO_ERR,
251 on_greeter_input, NULL);
252 lxcom_add_child_watch(greeter, on_greeter_exit, 0);
253 user=pw?pw->pw_uid:0;
254 return;
255 }
256 }
257 g_free(p);
258 first=FALSE;
259 }
260
261 int ui_main(void)
262 {
263 GMainLoop *loop = g_main_loop_new(NULL, 0);
264 if(greeter>0)
265 g_spawn_command_line_async("/etc/lxdm/LoginReady",NULL);
266 g_main_loop_run(loop);
267 return 0;
268 }