Imported Upstream version 0.1.0
[debian/lxdm.git] / src / lxdm.c
1 /*
2 * lxdm.c - main entry 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 #define _GNU_SOURCE
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27 #ifndef HAVE_LIBPAM
28 #define HAVE_LIBPAM 0
29 #endif
30 #ifndef HAVE_LIBXMU
31 #define HAVE_LIBXMU 0
32 #endif
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <ctype.h>
38 #include <unistd.h>
39 #include <stdarg.h>
40 #include <fcntl.h>
41 #include <pwd.h>
42 #include <grp.h>
43 #include <shadow.h>
44 #include <errno.h>
45 #include <signal.h>
46 #include <time.h>
47 #include <sys/wait.h>
48 #include <glib.h>
49 #include <gdk/gdk.h>
50 #include <gdk/gdkx.h>
51 #include <X11/Xlib.h>
52
53 #include <linux/vt.h>
54 #include <sys/ioctl.h>
55
56 #if HAVE_LIBXMU
57 #include <X11/Xmu/WinUtil.h>
58 #endif
59
60 #if HAVE_LIBPAM
61 #include <security/pam_appl.h>
62 #endif
63
64 #if HAVE_LIBCK_CONNECTOR
65 #include "ck-connector.h"
66 #endif
67
68 #include "lxdm.h"
69
70 GKeyFile *config;
71 static pid_t server;
72 #if HAVE_LIBCK_CONNECTOR
73 static CkConnector *ckc;
74 #endif
75 static Window *my_xid;
76 static unsigned int my_xid_n;
77 static char *self;
78 static pid_t child;
79 static int reason;
80 static char mcookie[33];
81 static int tty=7;
82
83 static int get_active_vt (void)
84 {
85 int console_fd;
86 struct vt_stat console_state = { 0 };
87
88 console_fd = open ("/dev/tty0", O_RDONLY | O_NOCTTY);
89
90 if (console_fd < 0) {
91 goto out;
92 }
93
94 if (ioctl (console_fd, VT_GETSTATE, &console_state) < 0) {
95 goto out;
96 }
97
98 out:
99 if (console_fd >= 0) {
100 close (console_fd);
101 }
102
103 return console_state.v_active;
104 }
105
106 static void set_active_vt(void)
107 {
108 int fd;
109
110 fd = open("/dev/console", O_RDWR);
111 if (fd < 0) {
112 fd = 0;
113 }
114 ioctl(fd, VT_ACTIVATE, tty);
115 if (fd != 0)
116 close(fd);
117 }
118
119 void lxdm_get_tty(void)
120 {
121 char *s=g_key_file_get_string(config,"server","arg",0);
122 int arc;
123 char **arg;
124 int len;
125 int gotvtarg=0;
126 int nr=0;
127 if(!s) s=g_strdup("/usr/bin/X");
128 g_shell_parse_argv(s,&arc,&arg,0);
129 g_free(s);
130 for(len=0;arg && arg[len];len++)
131 {
132 char *p=arg[len];
133 if(!strncmp(p,"vt",2) && isdigit(p[2]) &&
134 (!p[3] || (isdigit(p[3]) && !p[4])))
135 {
136 tty=atoi(p+2);
137 gotvtarg=1;
138 break;
139 }
140 }
141 if(!gotvtarg)
142 {
143 /* support plymouth */
144 nr=g_file_test("/var/spool/gdm/force-display-on-active-vt",G_FILE_TEST_EXISTS);
145 if(nr || g_key_file_get_integer(config,"server","active_vt",0))
146 {
147 /* get active vt dynamic */
148 tty=get_active_vt();
149 }
150 if(nr) unlink("/var/spool/gdm/force-display-on-active-vt");
151 }
152 arg=g_renew(char *,arg,len+10);
153 if(!gotvtarg)
154 arg[len++]=g_strdup_printf("vt%d",tty);
155 arg[len++]=g_strdup("-nolisten");
156 arg[len++]=g_strdup("tcp");
157 if(nr!=0)
158 arg[len++]=g_strdup("-nr");
159 arg[len]=NULL;
160 s=g_strjoinv(" ",arg);
161 g_strfreev(arg);
162 g_key_file_set_string(config,"server","arg",s);
163 g_free(s);
164 set_active_vt();
165 }
166
167 void lxdm_restart_self(void)
168 {
169 reason=0;
170 exit(0);
171 }
172
173 void lxdm_quit_self(void)
174 {
175 reason=1;
176 exit(0);
177 }
178
179 void log_print(char *fmt,...)
180 {
181 static FILE *log;
182 va_list ap;
183 if(!fmt)
184 {
185 if(log)
186 fclose(log);
187 log=0;
188 return;
189 }
190 if(!log)
191 {
192 log=fopen("/var/log/lxdm.log","w");
193 if(!log)
194 return;
195 }
196 va_start(ap,fmt);
197 vfprintf(log,fmt,ap);
198 va_end(ap);
199 fflush(log);
200 }
201
202 GSList *do_scan_xsessions(void)
203 {
204 GSList *l=NULL;
205 GDir *d;
206 LXSESSION *sess;
207 char *name;
208
209 d=g_dir_open("/usr/share/xsessions",0,NULL);
210 if(!d) return NULL;
211 while((name=(char*)g_dir_read_name(d))!=NULL)
212 {
213 GKeyFile *f=g_key_file_new();
214 char *tmp=g_strdup_printf("/usr/share/xsessions/%s",name);
215 gboolean ret=g_key_file_load_from_file(f,tmp,G_KEY_FILE_NONE,NULL);
216 while(ret==TRUE)
217 {
218 char *name=g_key_file_get_string(f,"Desktop Entry","Name",0);
219 if(!name) break;
220 char *exec=g_key_file_get_string(f,"Desktop Entry","Exec",0);
221 if(!exec)
222 {
223 g_free(name);
224 break;
225 }
226 sess=g_malloc(sizeof(LXSESSION));
227 sess->name=name;
228 sess->exec=exec;
229 if(!strcmp(name,"LXDE"))
230 l=g_slist_prepend(l,sess);
231 else
232 l=g_slist_append(l,sess);
233 break;
234 }
235 g_key_file_free(f);
236 }
237 g_dir_close(d);
238 return l;
239 }
240
241 void free_xsessions(GSList *l)
242 {
243 GSList *p;
244 LXSESSION *sess;
245
246 for(p=l;p;p=p->next)
247 {
248 sess=p->data;
249 g_free(sess->name);
250 g_free(sess->exec);
251 g_free(sess);
252 }
253 g_slist_free(l);
254 }
255
256 void create_server_auth(void)
257 {
258 GRand *h;
259 const char *digits = "0123456789abcdef";
260 int i,r,hex=0;
261 char *authfile;
262 char *tmp;
263
264 h=g_rand_new();
265 for(i=0;i<31;i++)
266 {
267 r=g_rand_int(h)%16;
268 mcookie[i] = digits[r];
269 if (r>9)
270 hex++;
271 }
272 if ((hex%2) == 0)
273 r = g_rand_int(h)%10;
274 else
275 r = g_rand_int(h)%5+10;
276 mcookie[31] = digits[r];
277 mcookie[32]=0;
278 g_rand_free(h);
279
280 authfile=g_key_file_get_string(config,"base","authfile",0);
281 if(!authfile)
282 authfile=g_strdup("/var/run/lxdm.auth");
283 tmp=g_strdup_printf("XAUTHORITY=%s",authfile);
284 putenv(tmp);
285 g_free(tmp);
286 remove(authfile);
287 tmp=g_strdup_printf("xauth -q -f %s add %s . %s",
288 authfile,getenv("DISPLAY"),mcookie);
289 system(tmp);
290 g_free(tmp);
291 g_free(authfile);
292 }
293
294 void create_client_auth(char *home)
295 {
296 char *tmp;
297 char *authfile;
298
299 if(getuid()==0) /* root don't need it */
300 return;
301
302 authfile=g_strdup_printf("%s/.Xauthority",home);
303 remove(authfile);
304 tmp=g_strdup_printf("xauth -q -f %s add %s . %s",
305 authfile,getenv("DISPLAY"),mcookie);
306 system(tmp);
307 g_free(authfile);
308 g_free(tmp);
309 }
310
311 int lxdm_auth_user(char *user,char *pass,struct passwd **ppw)
312 {
313 struct passwd *pw;
314 struct spwd *sp;
315 char *real;
316 char *enc;
317 if(!user)
318 return AUTH_ERROR;
319 if(!user[0])
320 return AUTH_BAD_USER;
321 pw=getpwnam(user);
322 endpwent();
323 if(!pw)
324 return AUTH_BAD_USER;
325 if(!pass)
326 {
327 *ppw=pw;
328 return AUTH_SUCCESS;
329 }
330 sp=getspnam(user);
331 if(!sp)
332 {
333 return AUTH_FAIL;
334 }
335 endspent();
336 real=sp->sp_pwdp;
337 if(!real || !real[0])
338 {
339 if(!pass[0])
340 {
341 *ppw=pw;
342 return AUTH_SUCCESS;
343 }
344 else
345 {
346 return AUTH_FAIL;
347 }
348 }
349 enc=crypt(pass,real);
350 if(strcmp(real,enc))
351 return AUTH_FAIL;
352 if(strstr(pw->pw_shell,"nologin"))
353 return AUTH_PRIV;
354 *ppw=pw;
355 return AUTH_SUCCESS;
356 }
357
358 #if HAVE_LIBPAM
359 static pam_handle_t *pamh;
360 static struct pam_conv conv;
361
362 void setup_pam_session(struct passwd *pw)
363 {
364 int err;
365 char x[256];
366 if(PAM_SUCCESS!=pam_start("lxdm",pw->pw_name,&conv,&pamh))
367 {
368 pamh=NULL;
369 return;
370 }
371 sprintf(x,"tty%d",tty);
372 pam_set_item(pamh,PAM_TTY,x);
373 #ifdef PAM_XDISPLAY
374 pam_set_item(pamh,PAM_XDISPLAY,getenv("DISPLAY"));
375 #endif
376 err=pam_open_session(pamh,0); /* FIXME pam session failed */
377 if(err!=PAM_SUCCESS)
378 {
379 log_print("pam open session error \"%s\"\n",pam_strerror(pamh,err));
380 }
381
382 }
383
384 void close_pam_session(void)
385 {
386 int err;
387 if(!pamh) return;
388 err=pam_close_session(pamh,0);
389 pam_end(pamh,err);
390 pamh=NULL;
391 }
392
393 #endif
394
395 void switch_user(struct passwd *pw,char *run,char **env)
396 {
397 if(!pw || initgroups(pw->pw_name, pw->pw_gid) ||
398 setgid(pw->pw_gid) || setuid(pw->pw_uid) || setsid()==-1)
399 {
400 exit(EXIT_FAILURE);
401 }
402 chdir(pw->pw_dir);
403 create_client_auth(pw->pw_dir);
404 execle("/etc/lxdm/Xsession","/etc/lxdm/Xsession",run,NULL,env);
405 exit(EXIT_FAILURE);
406 }
407
408 void get_lock(void)
409 {
410 FILE *fp;
411 char *lockfile;
412
413 lockfile=g_key_file_get_string(config,"base","lock",0);
414 if(!lockfile) lockfile=g_strdup("/var/run/lxdm.pid");
415
416 fp=fopen(lockfile,"r");
417 if(fp)
418 {
419 int pid;
420 int ret;
421 ret=fscanf(fp,"%d",&pid);
422 fclose(fp);
423 if(ret==1)
424 {
425 if(kill(pid,0)==0 || (ret==-1 && errno==EPERM))
426 {
427 exit(EXIT_SUCCESS);
428 }
429 }
430 }
431 fp=fopen(lockfile,"w");
432 if(!fp)
433 exit(EXIT_FAILURE);
434 fprintf(fp,"%d",getpid());
435 fclose(fp);
436 g_free(lockfile);
437 }
438
439 void put_lock(void)
440 {
441 FILE *fp;
442 char *lockfile;
443
444 lockfile=g_key_file_get_string(config,"base","lock",0);
445 if(!lockfile) lockfile=g_strdup("/var/run/lxdm.pid");
446 fp=fopen(lockfile,"r");
447 if(fp)
448 {
449 int pid;
450 int ret;
451 ret=fscanf(fp,"%d",&pid);
452 fclose(fp);
453 if(ret==1 && pid==getpid())
454 remove(lockfile);
455 }
456 g_free(lockfile);
457 }
458
459 void stop_pid(int pid)
460 {
461 if(pid<=0) return;
462 if(killpg(pid,SIGTERM)<0)
463 killpg(pid,SIGKILL);
464 if(kill(pid,0)==0)
465 {
466 if(kill(pid,SIGTERM))
467 kill(pid,SIGKILL);
468 while(1)
469 {
470 int wpid,status;
471 wpid=wait(&status);
472 if(pid==wpid) break;
473 }
474 }
475 while(waitpid(-1,0,WNOHANG)>0);
476 }
477
478 static void on_xserver_stop(GPid pid,gint status,gpointer data)
479 {
480 stop_pid(server);
481 server=-1;
482 lxdm_restart_self();
483 }
484
485 void startx(void)
486 {
487 char *arg;
488 char **args;
489
490 if(!getenv("DISPLAY"))
491 putenv("DISPLAY=:0");
492
493 create_server_auth();
494
495 arg=g_key_file_get_string(config,"server","arg",0);
496 if(!arg) arg=g_strdup("/usr/bin/X");
497 args=g_strsplit(arg," ",-1);
498 g_free(arg);
499
500 server=vfork();
501
502 switch(server){
503 case 0:
504 setpgid(0,getpid());
505 execvp(args[0], args);
506 break;
507 case -1:
508 exit(EXIT_FAILURE);
509 break;
510 default:
511 break;
512 }
513 g_strfreev(args);
514 g_child_watch_add(server,on_xserver_stop,0);
515 }
516
517 void exit_cb(void)
518 {
519 if(child>0)
520 {
521 killpg(child,SIGHUP);
522 stop_pid(child);
523 child=-1;
524 }
525 #if HAVE_LIBPAM
526 close_pam_session();
527 #endif
528 if(server>0)
529 {
530 stop_pid(server);
531 server=-1;
532 }
533 put_lock();
534 if(reason==0)
535 {
536 execlp(self,self,NULL);
537 }
538 }
539
540 int CatchErrors(Display *dpy, XErrorEvent *ev)
541 {
542 return 0;
543 }
544
545 void get_my_xid(void)
546 {
547 Window dummy,parent;
548 Display *Dpy=gdk_x11_get_default_xdisplay();
549 Window Root=gdk_x11_get_default_root_xwindow();
550 XQueryTree(Dpy, Root, &dummy, &parent, &my_xid, &my_xid_n);
551 }
552
553 int is_my_id(XID id)
554 {
555 int i;
556 if(!my_xid)
557 return 0;
558 for(i=0;i<my_xid_n;i++)
559 if(id==my_xid[i]) return 1;
560 return 0;
561 }
562
563 void free_my_xid(void)
564 {
565 XFree(my_xid);
566 my_xid=0;
567 }
568
569 void stop_clients(int top)
570 {
571 Window dummy,parent;
572 Window *children;
573 unsigned int nchildren;
574 unsigned int i;
575 XWindowAttributes attr;
576 Display *Dpy=gdk_x11_get_default_xdisplay();
577 Window Root=gdk_x11_get_default_root_xwindow();
578
579 XSync(Dpy, 0);
580 XSetErrorHandler(CatchErrors);
581
582 nchildren = 0;
583 XQueryTree(Dpy, Root, &dummy, &parent, &children, &nchildren);
584 if(!top)
585 {
586 for(i=0; i<nchildren; i++)
587 {
588 if(XGetWindowAttributes(Dpy, children[i], &attr) && (attr.map_state == IsViewable))
589 #if HAVE_LIBXMU
590 children[i] = XmuClientWindow(Dpy, children[i]);
591 #else
592 children[i]=children[i];
593 #endif
594 else
595 children[i] = 0;
596 }
597 }
598
599 for(i=0; i<nchildren; i++)
600 {
601 if(children[i] && !is_my_id(children[i]))
602 {
603 XKillClient(Dpy, children[i]);
604 //printf("kill %d\n",i);
605 }
606 }
607 XFree((char *)children);
608 XSync(Dpy, 0);
609 XSetErrorHandler(NULL);
610 }
611
612 static void on_session_stop(GPid pid,gint status,gpointer data)
613 {
614 int code=WEXITSTATUS(status);
615
616 killpg(pid,SIGHUP);
617 stop_pid(pid);
618 child=-1;
619
620 if(server>0)
621 {
622 /* FIXME just work around lxde bug of focus can't set */
623 //stop_clients(0);
624 stop_clients(1);
625 free_my_xid();
626 }
627 #if HAVE_LIBPAM
628 close_pam_session();
629 #endif
630 #if HAVE_LIBCK_CONNECTOR
631 if(ckc!=NULL)
632 {
633 DBusError error;
634 dbus_error_init (&error);
635 ck_connector_close_session(ckc, &error);
636 unsetenv("XDG_SESSION_COOKIE");
637 }
638 #endif
639 if(code==0)
640 {
641 /* xterm will quit use this, but we shul not quit here */
642 /* so wait someone to kill me may better */
643 //lxdm_quit_self();
644 sleep(2);
645 }
646
647 ui_prepare();
648 }
649
650 void lxdm_do_login(struct passwd *pw,char *session,char *lang)
651 {
652 int pid;
653
654 if (pw->pw_shell[0] == '\0')
655 {
656 setusershell();
657 strcpy(pw->pw_shell, getusershell());
658 endusershell();
659 }
660 #if HAVE_LIBPAM
661 setup_pam_session(pw);
662 #endif
663 #if HAVE_LIBCK_CONNECTOR
664 if(ckc!=NULL)
665 {
666 DBusError error;
667 char x[256],*d,*n;
668 sprintf(x,"/dev/tty%d",tty);
669 dbus_error_init (&error);
670 d=x;n=getenv("DISPLAY");
671 if(ck_connector_open_session_with_parameters(ckc,&error,
672 "unix-user",&pw->pw_uid,
673 "display-device",&d,
674 "x11-display-device",&d,
675 "x11-display",&n,
676 NULL))
677 {
678 setenv("XDG_SESSION_COOKIE",ck_connector_get_cookie(ckc),1);
679 }
680 }
681 #endif
682 get_my_xid();
683 child = pid = fork();
684 if(child==0)
685 {
686 char *env[12];
687 char *path;
688 int i=0;
689
690 env[i++]=g_strdup_printf("TERM=%s",getenv("TERM"));
691 env[i++]=g_strdup_printf("HOME=%s", pw->pw_dir);
692 env[i++]=g_strdup_printf("SHELL=%s", pw->pw_shell);
693 env[i++]=g_strdup_printf("USER=%s", pw->pw_name);
694 env[i++]=g_strdup_printf("LOGNAME=%s", pw->pw_name);
695 env[i++]=g_strdup_printf("DISPLAY=%s", getenv("DISPLAY"));
696 path=g_key_file_get_string(config,"base","path",0);
697 if(!path && getenv("PATH"))
698 path=g_strdup(getenv("PATH"));
699 if(!path)
700 path=g_strdup("/bin:/usr/bin");
701 env[i++]=g_strdup_printf("PATH=%s",path);
702 g_free(path);
703 if(lang && lang[0])
704 {
705 env[i++]=g_strdup_printf("LANG=%s",lang);
706 env[i++]=g_strdup_printf("LANGUAGE=%s",lang);
707 }
708 if(getenv("XDG_SESSION_COOKIE"))
709 env[i++]=g_strdup_printf("XDG_SESSION_COOKIE=%s",getenv("XDG_SESSION_COOKIE"));
710 env[i++]=0;
711
712 if(!session || !session[i]) /* this means use default session */
713 session=g_key_file_get_string(config,"base","session",0);
714 if(!session && getenv("PREFERRED"))
715 session=g_strdup(getenv("PREFERRED"));
716 if(!session && getenv("DESKTOP"))
717 {
718 char *p=getenv("DESKTOP");
719 if(!strcmp(p,"LXDE"))
720 session=g_strdup("/usr/bin/startlxde");
721 else if(!strcmp(p,"GNOME"))
722 session=g_strdup("/usr/bin/gnome-session");
723 else if(!strcmp(p,"KDE"))
724 session=g_strdup("/usr/bin/startkde");
725 else if(!strcmp(p,"XFCE"))
726 session=g_strdup("startxfce4");
727 else
728 session=g_strdup(p);
729 }
730 if(!session)
731 session=g_strdup("");
732
733 switch_user(pw,session,env);
734 reason=4;
735 exit(EXIT_FAILURE);
736 }
737 g_child_watch_add(pid,on_session_stop,0);
738 }
739
740 void lxdm_do_reboot(void)
741 {
742 char *cmd;
743 cmd=g_key_file_get_string(config,"cmd","reboot",0);
744 if(!cmd) cmd=g_strdup("reboot");
745 reason=1;
746 system(cmd);
747 g_free(cmd);
748 lxdm_quit_self();
749 }
750
751 void lxdm_do_shutdown(void)
752 {
753 char *cmd;
754 cmd=g_key_file_get_string(config,"cmd","shutdown",0);
755 if(!cmd) cmd=g_strdup("shutdown -h now");
756 reason=1;
757 system(cmd);
758 g_free(cmd);
759 lxdm_quit_self();
760 }
761
762 int lxdm_cur_session(void)
763 {
764 return child;
765 }
766
767 int lxdm_do_auto_login(void)
768 {
769 struct passwd *pw;
770 char *user;
771
772 user=g_key_file_get_string(config,"base","autologin",0);
773 if(!user)
774 return 0;
775 if(AUTH_SUCCESS!=lxdm_auth_user(user,0,&pw))
776 return 0;
777 lxdm_do_login(pw,NULL,NULL);
778 return 1;
779 }
780
781 void sig_handler(int sig)
782 {
783 log_print("catch signal %d\n",sig);
784 switch(sig){
785 case SIGTERM:
786 case SIGINT:
787 lxdm_quit_self();
788 break;
789 default:
790 break;
791 }
792 }
793
794 void set_signal(void)
795 {
796 signal(SIGQUIT, sig_handler);
797 signal(SIGTERM, sig_handler);
798 signal(SIGKILL, sig_handler);
799 signal(SIGINT, sig_handler);
800 signal(SIGHUP, sig_handler);
801 signal(SIGPIPE, sig_handler);
802 signal(SIGUSR1, sig_handler);
803 signal(SIGALRM, sig_handler);
804 }
805
806 #if HAVE_LIBCK_CONNECTOR
807 void init_ck(void)
808 {
809 ckc=ck_connector_new();
810 }
811 #endif
812
813 static void apply_theme(void)
814 {
815 GKeyFile *tmp;
816 gchar **grps;
817 char *p;
818 gsize len;
819 FILE *fp;
820
821 config=g_key_file_new();
822 g_key_file_load_from_file(config,"/etc/lxdm/lxdm.conf",G_KEY_FILE_KEEP_COMMENTS,NULL);
823
824 p=g_key_file_get_string(config,"display","theme",0);
825 if(!p || !p[0])
826 {
827 g_free(p);
828 g_key_file_free(config);
829 return;
830 }
831
832 tmp=g_key_file_new();
833 g_key_file_load_from_file(config,p,G_KEY_FILE_NONE,NULL);
834 g_free(p);
835 grps=g_key_file_get_groups(tmp,NULL);
836 if(grps)
837 {
838 int i,j;
839 char **keys,*val;
840 for(i=0;grps[i];i++)
841 {
842 keys=g_key_file_get_keys(tmp,grps[i],NULL,NULL);
843 if(!keys) continue;
844 for(j=0;keys[j];j++)
845 {
846 val=g_key_file_get_string(tmp,grps[i],keys[j],NULL);
847 if(!val) continue;
848 g_key_file_set_string(config,grps[i],keys[j],val);
849 g_free(val);
850 }
851 g_strfreev(keys);
852 }
853 }
854 g_strfreev(grps);
855 g_key_file_free(tmp);
856
857 p=g_key_file_to_data(config,&len,NULL);
858 fp=fopen("/etc/lxdm/lxdm.conf","w");
859 if(fp)
860 {
861 fwrite(p,1,len,fp);
862 fclose(fp);
863 }
864 g_free(p);
865 g_key_file_free(config);
866 }
867
868
869 int main(int arc,char *arg[])
870 {
871 int tmp;
872 int daemonmode=0;
873
874 if(getuid()!=0)
875 {
876 printf("only root allow to use this program\n");
877 exit(EXIT_FAILURE);
878 }
879
880 while((tmp=getopt(arc,arg,"hd"))!=EOF)
881 {
882 switch(tmp){
883 case 'd':
884 daemonmode=1;
885 break;
886 case 'a': /* apply theme default settings */
887 apply_theme();
888 exit(EXIT_SUCCESS);
889 break;
890 case 'h':
891 printf("usage: lxdm [options ...]\n");
892 printf("options:\n");
893 printf(" -d: daemon mode\n");
894 exit(EXIT_SUCCESS);
895 break;
896 }
897 }
898
899 if(daemonmode)
900 daemon(1,1);
901
902 self=arg[0];
903
904 config=g_key_file_new();
905 g_key_file_load_from_file(config,"/etc/lxdm/lxdm.conf",G_KEY_FILE_NONE,NULL);
906
907 get_lock();
908 atexit(exit_cb);
909
910 set_signal();
911 lxdm_get_tty();
912 startx();
913
914 for(tmp=0;tmp<200;tmp++)
915 {
916 if(gdk_init_check(0,0))
917 break;
918 usleep(50*1000);
919 }
920 if(tmp>=200)
921 exit(EXIT_FAILURE);
922
923 #if HAVE_LIBCK_CONNECTOR
924 init_ck();
925 #endif
926
927 lxdm_do_auto_login();
928
929 ui_main();
930
931 lxdm_restart_self();
932
933 return 0;
934 }