summaryrefslogtreecommitdiff
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--core/opie-login/loginapplication.cpp74
-rw-r--r--core/opie-login/loginapplication.h6
-rw-r--r--core/opie-login/main.cpp12
3 files changed, 82 insertions, 10 deletions
diff --git a/core/opie-login/loginapplication.cpp b/core/opie-login/loginapplication.cpp
index 8d86a71..1facf2d 100644
--- a/core/opie-login/loginapplication.cpp
+++ b/core/opie-login/loginapplication.cpp
@@ -1,221 +1,281 @@
1/* 1/*
2               =. This file is part of the OPIE Project 2               =. This file is part of the OPIE Project
3             .=l. Copyright (c) 2002 Robert Griebl <sandman@handhelds.org> 3             .=l. Copyright (c) 2002 Robert Griebl <sandman@handhelds.org>
4           .>+-= 4           .>+-=
5 _;:,     .>    :=|. This file is free software; you can 5 _;:,     .>    :=|. This file is free software; you can
6.> <`_,   >  .   <= redistribute it and/or modify it under 6.> <`_,   >  .   <= redistribute it and/or modify it under
7:`=1 )Y*s>-.--   : the terms of the GNU General Public 7:`=1 )Y*s>-.--   : the terms of the GNU General Public
8.="- .-=="i,     .._ License as published by the Free Software 8.="- .-=="i,     .._ License as published by the Free Software
9 - .   .-<_>     .<> Foundation; either version 2 of the License, 9 - .   .-<_>     .<> Foundation; either version 2 of the License,
10     ._= =}       : or (at your option) any later version. 10     ._= =}       : or (at your option) any later version.
11    .%`+i>       _;_. 11    .%`+i>       _;_.
12    .i_,=:_.      -<s. This file is distributed in the hope that 12    .i_,=:_.      -<s. This file is distributed in the hope that
13     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY; 13     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
14    : ..    .:,     . . . without even the implied warranty of 14    : ..    .:,     . . . without even the implied warranty of
15    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A 15    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
16  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU General 16  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU General
17..}^=.=       =       ; Public License for more details. 17..}^=.=       =       ; Public License for more details.
18++=   -.     .`     .: 18++=   -.     .`     .:
19 :     =  ...= . :.=- You should have received a copy of the GNU 19 :     =  ...= . :.=- You should have received a copy of the GNU
20 -.   .:....=;==+<; General Public License along with this file; 20 -.   .:....=;==+<; General Public License along with this file;
21  -_. . .   )=.  = see the file COPYING. If not, write to the 21  -_. . .   )=.  = see the file COPYING. If not, write to the
22    --        :-=` Free Software Foundation, Inc., 22    --        :-=` Free Software Foundation, Inc.,
23 59 Temple Place - Suite 330, 23 59 Temple Place - Suite 330,
24 Boston, MA 02111-1307, USA. 24 Boston, MA 02111-1307, USA.
25 25
26*/ 26*/
27 27
28#include <pwd.h> 28#include <pwd.h>
29#include <grp.h> 29#include <grp.h>
30#include <unistd.h> 30#include <unistd.h>
31#include <stdlib.h> 31#include <stdlib.h>
32#include <signal.h> 32#include <signal.h>
33#include <sys/stat.h>
34#include <sys/wait.h>
33 35
34#ifdef USEPAM 36#ifdef USEPAM
35extern "C" { 37extern "C" {
36#include <security/pam_appl.h> 38#include <security/pam_appl.h>
37} 39}
38#else 40#else
39#include <crypt.h> 41#include <crypt.h>
40#include <shadow.h> 42#include <shadow.h>
41#endif 43#endif
42 44
43#include "loginapplication.h" 45#include "loginapplication.h"
44 46
45LoginApplication *lApp; 47LoginApplication *lApp;
46 48
47LoginApplication::LoginApplication ( int &argc, char **argv, pid_t parentpid ) 49LoginApplication::LoginApplication ( int &argc, char **argv, pid_t parentpid )
48 : QPEApplication ( argc, argv, GuiServer ) 50 : QPEApplication ( argc, argv, GuiServer )
49{ 51{
50 lApp = this; 52 lApp = this;
51 m_parentpid = parentpid; 53 m_parentpid = parentpid;
52} 54}
53 55
54const char *LoginApplication::s_username = 0; 56const char *LoginApplication::s_username = 0;
55 57
56#ifdef USEPAM 58#ifdef USEPAM
57 59
58const char *LoginApplication::s_pam_password = 0; 60const char *LoginApplication::s_pam_password = 0;
59 61
60int LoginApplication::pam_helper ( int num_msg, const struct pam_message **msg, struct pam_response **resp, void * ) 62int LoginApplication::pam_helper ( int num_msg, const struct pam_message **msg, struct pam_response **resp, void * )
61{ 63{
62 int replies = 0; 64 int replies = 0;
63 struct pam_response *reply = 0; 65 struct pam_response *reply = 0;
64 int size = sizeof( struct pam_response ); 66 int size = sizeof( struct pam_response );
65 67
66 for ( int i = 0; i < num_msg; i++ ) { 68 for ( int i = 0; i < num_msg; i++ ) {
67 switch ( msg [i]-> msg_style ) { 69 switch ( msg [i]-> msg_style ) {
68 case PAM_PROMPT_ECHO_ON: // user name given to PAM already 70 case PAM_PROMPT_ECHO_ON: // user name given to PAM already
69 return PAM_CONV_ERR; 71 return PAM_CONV_ERR;
70 72
71 case PAM_PROMPT_ECHO_OFF: // wants password 73 case PAM_PROMPT_ECHO_OFF: // wants password
72 reply = (struct pam_response *) ::realloc ( reply, size ); 74 reply = (struct pam_response *) ::realloc ( reply, size );
73 if ( !reply ) 75 if ( !reply )
74 return PAM_CONV_ERR; 76 return PAM_CONV_ERR;
75 size += sizeof( struct pam_response ); 77 size += sizeof( struct pam_response );
76 78
77 reply [replies]. resp_retcode = PAM_SUCCESS; 79 reply [replies]. resp_retcode = PAM_SUCCESS;
78 reply [replies]. resp = ::strdup ( s_pam_password ); 80 reply [replies]. resp = ::strdup ( s_pam_password );
79 replies++; // PAM frees resp 81 replies++; // PAM frees resp
80 break; 82 break;
81 83
82 case PAM_TEXT_INFO: 84 case PAM_TEXT_INFO:
83 break; 85 break;
84 86
85 default: 87 default:
86 /* unknown or PAM_ERROR_MSG */ 88 /* unknown or PAM_ERROR_MSG */
87 if ( reply ) 89 if ( reply )
88 ::free ( reply ); 90 ::free ( reply );
89 return PAM_CONV_ERR; 91 return PAM_CONV_ERR;
90 } 92 }
91 } 93 }
92 if ( reply ) 94 if ( reply )
93 *resp = reply; 95 *resp = reply;
94 return PAM_SUCCESS; 96 return PAM_SUCCESS;
95} 97}
96 98
97 99
98bool LoginApplication::checkPassword ( const char *user, const char *pass ) 100bool LoginApplication::checkPassword ( const char *user, const char *pass )
99{ 101{
100 static struct pam_conv conv = { &LoginApplication::pam_helper, 0 }; 102 static struct pam_conv conv = { &LoginApplication::pam_helper, 0 };
101 103
102 int pam_error; 104 int pam_error;
103 pam_handle_t *pamh = 0; 105 pam_handle_t *pamh = 0;
104 106
105 pam_error = ::pam_start( "xdm", user, &conv, &pamh ); 107 pam_error = ::pam_start( "xdm", user, &conv, &pamh );
106 if ( pam_error == PAM_SUCCESS ) { 108 if ( pam_error == PAM_SUCCESS ) {
107 s_pam_password = pass; 109 s_pam_password = pass;
108 pam_error = ::pam_authenticate ( pamh, 0 ); 110 pam_error = ::pam_authenticate ( pamh, 0 );
109 s_pam_password = 0; 111 s_pam_password = 0;
110 } 112 }
111 ::pam_end ( pamh, pam_error ); 113 ::pam_end ( pamh, pam_error );
112 return ( pam_error == PAM_SUCCESS ); 114 return ( pam_error == PAM_SUCCESS );
113} 115}
114 116
115#else 117#else
116 118
117bool LoginApplication::checkPassword ( const char *user, const char *pass ) 119bool LoginApplication::checkPassword ( const char *user, const char *pass )
118{ 120{
119 char *encrypted, *correct; 121 char *encrypted, *correct;
120 struct passwd *pw; 122 struct passwd *pw;
121 123
122 if ( !user || !pass ) 124 if ( !user || !pass )
123 return false; 125 return false;
124 126
125 pw = ::getpwnam ( user ); 127 pw = ::getpwnam ( user );
126 128
127 if ( !pw ) 129 if ( !pw )
128 return false; 130 return false;
129 131
130 if (( ::strcmp ( pw-> pw_passwd, "x" ) == 0 ) || ( ::strcmp ( pw-> pw_passwd, "*" ) == 0 )) { 132 if (( ::strcmp ( pw-> pw_passwd, "x" ) == 0 ) || ( ::strcmp ( pw-> pw_passwd, "*" ) == 0 )) {
131 struct spwd *sp = ::getspnam ( pw-> pw_name ); 133 struct spwd *sp = ::getspnam ( pw-> pw_name );
132 134
133 if ( !sp ) 135 if ( !sp )
134 return false; 136 return false;
135 137
136 correct = sp-> sp_pwdp; 138 correct = sp-> sp_pwdp;
137 } 139 }
138 else 140 else
139 correct = pw-> pw_passwd; 141 correct = pw-> pw_passwd;
140 142
141 if ( correct == 0 || correct[0] == '\0' ) 143 if ( correct == 0 || correct[0] == '\0' )
142 return true; 144 return true;
143 145
144 encrypted = ::crypt ( pass, correct ); 146 encrypted = ::crypt ( pass, correct );
145 return ( ::strcmp ( encrypted, correct ) == 0 ); 147 return ( ::strcmp ( encrypted, correct ) == 0 );
146} 148}
147 149
148#endif 150#endif
149 151
150bool LoginApplication::changeIdentity ( ) 152bool LoginApplication::changeIdentity ( )
151{ 153{
152 const char *DEFAULT_LOGIN_PATH = "/bin:/usr/bin"; 154 const char *DEFAULT_LOGIN_PATH = "/bin:/usr/bin";
153 const char *DEFAULT_ROOT_LOGIN_PATH = "/usr/sbin:/bin:/usr/bin:/sbin"; 155 const char *DEFAULT_ROOT_LOGIN_PATH = "/usr/sbin:/bin:/usr/bin:/sbin";
154 156
155 if ( !s_username ) 157 if ( !s_username )
156 return false; 158 return false;
157 struct passwd *pw = ::getpwnam ( s_username ); 159 struct passwd *pw = ::getpwnam ( s_username );
158 if ( !pw ) 160 if ( !pw )
159 return false; 161 return false;
160 162
163 // we are still root at this point - try to run the pre-session script
164 if ( !runRootScript ( "OPIEDIR", "share/opie-login/pre-session", s_username ))
165 qWarning ( "failed to run $OPIEDIR/share/opie-login/pre-session" );
166
161 bool fail = false; 167 bool fail = false;
162 fail |= ( ::initgroups ( pw-> pw_name, pw-> pw_gid )); 168 fail |= ( ::initgroups ( pw-> pw_name, pw-> pw_gid ));
163 ::endgrent ( ); 169 ::endgrent ( );
164 fail |= ( ::setgid ( pw-> pw_gid )); 170 fail |= ( ::setgid ( pw-> pw_gid ));
165 fail |= ( ::setuid ( pw-> pw_uid )); 171 fail |= ( ::setuid ( pw-> pw_uid ));
166 172
167 fail |= ( ::chdir ( pw-> pw_dir ) && ::chdir ( "/" )); 173 fail |= ( ::chdir ( pw-> pw_dir ) && ::chdir ( "/" ));
168 174
169 fail |= ( ::setenv ( "HOME", pw-> pw_dir, 1 )); 175 fail |= ( ::setenv ( "HOME", pw-> pw_dir, 1 ));
170 fail |= ( ::setenv ( "SHELL", pw-> pw_shell, 1 )); 176 fail |= ( ::setenv ( "SHELL", pw-> pw_shell, 1 ));
171 fail |= ( ::setenv ( "USER", pw-> pw_name, 1 )); 177 fail |= ( ::setenv ( "USER", pw-> pw_name, 1 ));
172 fail |= ( ::setenv ( "LOGNAME", pw-> pw_name, 1 )); 178 fail |= ( ::setenv ( "LOGNAME", pw-> pw_name, 1 ));
173 fail |= ( ::setenv ( "PATH", ( pw-> pw_uid ? DEFAULT_LOGIN_PATH : DEFAULT_ROOT_LOGIN_PATH ), 1 )); 179 fail |= ( ::setenv ( "PATH", ( pw-> pw_uid ? DEFAULT_LOGIN_PATH : DEFAULT_ROOT_LOGIN_PATH ), 1 ));
174 180
175 return !fail; 181 return !fail;
176} 182}
177 183
178bool LoginApplication::login ( ) 184bool LoginApplication::login ( )
179{ 185{
180 char *opie = ::getenv ( "OPIEDIR" ); 186 execUserScript ( "HOME", ".opie-session" );
181 char *arg = new char [::strlen ( opie ) + 8 + 1]; 187 execUserScript ( "OPIEDIR", "share/opie-login/opie-session" );
188 execUserScript ( "OPIEDIR", "bin/qpe" );
189
190 qWarning ( "failed to start an Opie session" );
191 return false;
192}
193
194void LoginApplication::logout ( )
195{
196 // we are now root again - try to run the post-session script
197 if ( !runRootScript ( "OPIEDIR", "share/opie-login/post-session" ))
198 qWarning ( "failed to run $OPIEDIR/scripts/post-session" );
199}
182 200
183 ::strcpy ( arg, opie );
184 ::strcat ( arg, "/bin/qpe" );
185 201
186 // start qpe via a login shell 202static char *buildarg ( const char *base, const char *script )
187 ::execl ( "/bin/sh", "-sh", "-c", arg, 0 ); 203{
204 const char *dir = base ? ::getenv ( base ) : "/";
205 char *arg = new char [::strlen ( dir ) + ::strlen ( script ) + 2];
188 206
189 return false; 207 ::strcpy ( arg, dir );
208 ::strcat ( arg, "/" );
209 ::strcat ( arg, script );
210
211 return arg;
212}
213
214bool LoginApplication::runRootScript ( const char *base, const char *script, const char *param )
215{
216 bool res = false;
217 char *arg = buildarg ( base, script );
218
219 struct stat st;
220 if (( ::stat ( arg, &st ) == 0 ) && ( st. st_uid == 0 )) {
221 pid_t child = ::fork ( );
222
223 if ( child == 0 ) {
224 ::execl ( "/bin/sh", "-sh", arg, param, 0 );
225 ::_exit ( -1 );
226 }
227 else if ( child > 0 ) {
228 int status = 0;
229
230 while ( ::waitpid ( child, &status, 0 ) < 0 ) { }
231 res = ( WIFEXITED( status )) && ( WEXITSTATUS( status ) == 0 );
232 }
233 }
234
235 delete [] arg;
236 return res;
237}
238
239void LoginApplication::execUserScript ( const char *base, const char *script )
240{
241 char *arg = buildarg ( base, script );
242
243 struct stat st;
244 if ( ::stat ( arg, &st ) == 0 ) {
245 if ( st. st_mode & S_IXUSR )
246 ::execl ( "/bin/sh", "-sh", "-c", arg, 0 );
247 else
248 ::execl ( "/bin/sh", "-sh", arg, 0 );
249 }
190} 250}
191 251
192const char *LoginApplication::loginAs ( ) 252const char *LoginApplication::loginAs ( )
193{ 253{
194 return s_username; 254 return s_username;
195} 255}
196 256
197void LoginApplication::setLoginAs ( const char *name ) 257void LoginApplication::setLoginAs ( const char *name )
198{ 258{
199 s_username = name; 259 s_username = name;
200} 260}
201 261
202QStringList LoginApplication::allUsers ( ) 262QStringList LoginApplication::allUsers ( )
203{ 263{
204 struct passwd *pwd; 264 struct passwd *pwd;
205 QStringList sl; 265 QStringList sl;
206 266
207 while (( pwd = ::getpwent ( ))) { 267 while (( pwd = ::getpwent ( ))) {
208 if (( pwd-> pw_uid == 0 ) || ( pwd-> pw_uid >= 500 && pwd-> pw_uid < 65534 )) 268 if (( pwd-> pw_uid == 0 ) || ( pwd-> pw_uid >= 500 && pwd-> pw_uid < 65534 ))
209 sl << QString ( pwd-> pw_name ); 269 sl << QString ( pwd-> pw_name );
210 } 270 }
211 271
212 ::endpwent ( ); 272 ::endpwent ( );
213 273
214 return sl; 274 return sl;
215} 275}
216 276
217void LoginApplication::quitToConsole ( ) 277void LoginApplication::quitToConsole ( )
218{ 278{
219 QPEApplication::quit ( ); 279 QPEApplication::quit ( );
220 ::kill ( m_parentpid, SIGTERM ); 280 ::kill ( m_parentpid, SIGTERM );
221} 281}
diff --git a/core/opie-login/loginapplication.h b/core/opie-login/loginapplication.h
index 4e7cf79..d8264ea 100644
--- a/core/opie-login/loginapplication.h
+++ b/core/opie-login/loginapplication.h
@@ -1,70 +1,74 @@
1/* 1/*
2               =. This file is part of the OPIE Project 2               =. This file is part of the OPIE Project
3             .=l. Copyright (c) 2002 Robert Griebl <sandman@handhelds.org> 3             .=l. Copyright (c) 2002 Robert Griebl <sandman@handhelds.org>
4           .>+-= 4           .>+-=
5 _;:,     .>    :=|. This file is free software; you can 5 _;:,     .>    :=|. This file is free software; you can
6.> <`_,   >  .   <= redistribute it and/or modify it under 6.> <`_,   >  .   <= redistribute it and/or modify it under
7:`=1 )Y*s>-.--   : the terms of the GNU General Public 7:`=1 )Y*s>-.--   : the terms of the GNU General Public
8.="- .-=="i,     .._ License as published by the Free Software 8.="- .-=="i,     .._ License as published by the Free Software
9 - .   .-<_>     .<> Foundation; either version 2 of the License, 9 - .   .-<_>     .<> Foundation; either version 2 of the License,
10     ._= =}       : or (at your option) any later version. 10     ._= =}       : or (at your option) any later version.
11    .%`+i>       _;_. 11    .%`+i>       _;_.
12    .i_,=:_.      -<s. This file is distributed in the hope that 12    .i_,=:_.      -<s. This file is distributed in the hope that
13     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY; 13     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
14    : ..    .:,     . . . without even the implied warranty of 14    : ..    .:,     . . . without even the implied warranty of
15    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A 15    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
16  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU General 16  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU General
17..}^=.=       =       ; Public License for more details. 17..}^=.=       =       ; Public License for more details.
18++=   -.     .`     .: 18++=   -.     .`     .:
19 :     =  ...= . :.=- You should have received a copy of the GNU 19 :     =  ...= . :.=- You should have received a copy of the GNU
20 -.   .:....=;==+<; General Public License along with this file; 20 -.   .:....=;==+<; General Public License along with this file;
21  -_. . .   )=.  = see the file COPYING. If not, write to the 21  -_. . .   )=.  = see the file COPYING. If not, write to the
22    --        :-=` Free Software Foundation, Inc., 22    --        :-=` Free Software Foundation, Inc.,
23 59 Temple Place - Suite 330, 23 59 Temple Place - Suite 330,
24 Boston, MA 02111-1307, USA. 24 Boston, MA 02111-1307, USA.
25 25
26*/ 26*/
27 27
28#ifndef __OPIE_LOGINAPPLICATION_H__ 28#ifndef __OPIE_LOGINAPPLICATION_H__
29#define __OPIE_LOGINAPPLICATION_H__ 29#define __OPIE_LOGINAPPLICATION_H__
30 30
31#include <sys/types.h>
31#include <qstringlist.h> 32#include <qstringlist.h>
32
33#include <qpe/qpeapplication.h> 33#include <qpe/qpeapplication.h>
34 34
35#ifdef USEPAM 35#ifdef USEPAM
36struct pam_message; 36struct pam_message;
37struct pam_response; 37struct pam_response;
38#endif 38#endif
39 39
40class LoginApplication : public QPEApplication { 40class LoginApplication : public QPEApplication {
41public: 41public:
42 LoginApplication ( int &argc, char **argv, pid_t parentpid ); 42 LoginApplication ( int &argc, char **argv, pid_t parentpid );
43 43
44 static bool checkPassword ( const char *user, const char *password ); 44 static bool checkPassword ( const char *user, const char *password );
45 45
46 static const char *loginAs ( ); 46 static const char *loginAs ( );
47 static void setLoginAs ( const char *user ); 47 static void setLoginAs ( const char *user );
48 48
49 static bool changeIdentity ( ); 49 static bool changeIdentity ( );
50 static bool login ( ); 50 static bool login ( );
51 static void logout ( );
51 52
52 static QStringList allUsers ( ); 53 static QStringList allUsers ( );
53 54
54 void quitToConsole ( ); 55 void quitToConsole ( );
55 56
57 static bool runRootScript ( const char *base, const char *script, const char *param = 0 );
58 static void execUserScript ( const char *base, const char *script );
59
56private: 60private:
57 static const char *s_username; 61 static const char *s_username;
58 62
59#ifdef USEPAM 63#ifdef USEPAM
60 static int pam_helper ( int num_msg, const struct pam_message **msg, struct pam_response **resp, void * ); 64 static int pam_helper ( int num_msg, const struct pam_message **msg, struct pam_response **resp, void * );
61 static const char *s_pam_password; 65 static const char *s_pam_password;
62#endif 66#endif
63 67
64private: 68private:
65 pid_t m_parentpid; 69 pid_t m_parentpid;
66}; 70};
67 71
68extern LoginApplication *lApp; 72extern LoginApplication *lApp;
69 73
70#endif 74#endif
diff --git a/core/opie-login/main.cpp b/core/opie-login/main.cpp
index 674829d..81f4d1e 100644
--- a/core/opie-login/main.cpp
+++ b/core/opie-login/main.cpp
@@ -1,360 +1,368 @@
1/* 1/*
2               =. This file is part of the OPIE Project 2               =. This file is part of the OPIE Project
3             .=l. Copyright (c) 2002 Robert Griebl <sandman@handhelds.org> 3             .=l. Copyright (c) 2002 Robert Griebl <sandman@handhelds.org>
4           .>+-= 4           .>+-=
5 _;:,     .>    :=|. This file is free software; you can 5 _;:,     .>    :=|. This file is free software; you can
6.> <`_,   >  .   <= redistribute it and/or modify it under 6.> <`_,   >  .   <= redistribute it and/or modify it under
7:`=1 )Y*s>-.--   : the terms of the GNU General Public 7:`=1 )Y*s>-.--   : the terms of the GNU General Public
8.="- .-=="i,     .._ License as published by the Free Software 8.="- .-=="i,     .._ License as published by the Free Software
9 - .   .-<_>     .<> Foundation; either version 2 of the License, 9 - .   .-<_>     .<> Foundation; either version 2 of the License,
10     ._= =}       : or (at your option) any later version. 10     ._= =}       : or (at your option) any later version.
11    .%`+i>       _;_. 11    .%`+i>       _;_.
12    .i_,=:_.      -<s. This file is distributed in the hope that 12    .i_,=:_.      -<s. This file is distributed in the hope that
13     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY; 13     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
14    : ..    .:,     . . . without even the implied warranty of 14    : ..    .:,     . . . without even the implied warranty of
15    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A 15    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
16  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU General 16  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU General
17..}^=.=       =       ; Public License for more details. 17..}^=.=       =       ; Public License for more details.
18++=   -.     .`     .: 18++=   -.     .`     .:
19 :     =  ...= . :.=- You should have received a copy of the GNU 19 :     =  ...= . :.=- You should have received a copy of the GNU
20 -.   .:....=;==+<; General Public License along with this file; 20 -.   .:....=;==+<; General Public License along with this file;
21  -_. . .   )=.  = see the file COPYING. If not, write to the 21  -_. . .   )=.  = see the file COPYING. If not, write to the
22    --        :-=` Free Software Foundation, Inc., 22    --        :-=` Free Software Foundation, Inc.,
23 59 Temple Place - Suite 330, 23 59 Temple Place - Suite 330,
24 Boston, MA 02111-1307, USA. 24 Boston, MA 02111-1307, USA.
25 25
26*/ 26*/
27 27
28#define _GNU_SOURCE 28#define _GNU_SOURCE
29 29
30#include <sys/types.h> 30#include <sys/types.h>
31#include <time.h> 31#include <time.h>
32#include <sys/time.h> 32#include <sys/time.h>
33#include <sys/resource.h> 33#include <sys/resource.h>
34#include <unistd.h> 34#include <unistd.h>
35#include <syslog.h> 35#include <syslog.h>
36#include <sys/wait.h> 36#include <sys/wait.h>
37#include <stdio.h> 37#include <stdio.h>
38#include <stdlib.h> 38#include <stdlib.h>
39#include <signal.h> 39#include <signal.h>
40#include <getopt.h> 40#include <getopt.h>
41#include <string.h> 41#include <string.h>
42 42
43#include <qpe/qpeapplication.h> 43#include <qpe/qpeapplication.h>
44#include <qpe/qcopenvelope_qws.h> 44#include <qpe/qcopenvelope_qws.h>
45#include <qpe/qpestyle.h> 45#include <qpe/qpestyle.h>
46#include <qpe/power.h> 46#include <qpe/power.h>
47#include <qpe/config.h> 47#include <qpe/config.h>
48 48
49#include <opie/odevice.h> 49#include <opie/odevice.h>
50 50
51#include <qwindowsystem_qws.h> 51#include <qwindowsystem_qws.h>
52#include <qmessagebox.h> 52#include <qmessagebox.h>
53#include <qlabel.h> 53#include <qlabel.h>
54#include <qtimer.h> 54#include <qtimer.h>
55#include <qfile.h> 55#include <qfile.h>
56 56
57#include "loginapplication.h" 57#include "loginapplication.h"
58#include "loginwindowimpl.h" 58#include "loginwindowimpl.h"
59#include "calibrate.h" 59#include "calibrate.h"
60 60
61using namespace Opie; 61using namespace Opie;
62 62
63int login_main ( int argc, char **argv, pid_t ppid ); 63int login_main ( int argc, char **argv, pid_t ppid );
64void sigterm ( int sig ); 64void sigterm ( int sig );
65void sigint ( int sig );
65void exit_closelog ( ); 66void exit_closelog ( );
66 67
67static struct option long_options [] = { 68static struct option long_options [] = {
68 { "autologin", 1, 0, 'a' }, 69 { "autologin", 1, 0, 'a' },
69 { 0, 0, 0, 0 } 70 { 0, 0, 0, 0 }
70}; 71};
71 72
72 73
73int main ( int argc, char **argv ) 74int main ( int argc, char **argv )
74{ 75{
75 pid_t ppid = ::getpid ( ); 76 pid_t ppid = ::getpid ( );
76 77
77
78 if ( ::geteuid ( ) != 0 ) { 78 if ( ::geteuid ( ) != 0 ) {
79 ::fprintf ( stderr, "%s can only be executed by root. (or chmod +s)", argv [0] ); 79 ::fprintf ( stderr, "%s can only be executed by root. (or chmod +s)", argv [0] );
80 return 1; 80 return 1;
81 } 81 }
82 if ( ::getuid ( ) != 0 ) // qt doesn't really like SUID and 82 if ( ::getuid ( ) != 0 ) // qt doesn't really like SUID and
83 ::setuid ( 0 ); // messes up things like config files 83 ::setuid ( 0 ); // messes up things like config files
84 84
85 char *autolog = 0; 85 char *autolog = 0;
86 int c; 86 int c;
87 while (( c = ::getopt_long ( argc, argv, "a:", long_options, 0 )) != -1 ) { 87 while (( c = ::getopt_long ( argc, argv, "a:", long_options, 0 )) != -1 ) {
88 switch ( c ) { 88 switch ( c ) {
89 case 'a': 89 case 'a':
90 autolog = optarg; 90 autolog = optarg;
91 break; 91 break;
92 default: 92 default:
93 ::fprintf ( stderr, "Usage: %s [-a|--autologin=<user>]\n", argv [0] ); 93 ::fprintf ( stderr, "Usage: %s [-a|--autologin=<user>]\n", argv [0] );
94 return 2; 94 return 2;
95 } 95 }
96 } 96 }
97 97
98 //struct rlimit rl; 98 //struct rlimit rl;
99 //::getrlimit ( RLIMIT_NOFILE, &rl ); 99 //::getrlimit ( RLIMIT_NOFILE, &rl );
100 100
101 //for ( unsigned int i = 0; i < rl. rlim_cur; i++ ) 101 //for ( unsigned int i = 0; i < rl. rlim_cur; i++ )
102 // ::close ( i ); 102 // ::close ( i );
103 103
104 ::setpgid ( 0, 0 ); 104 ::setpgid ( 0, 0 );
105 ::setsid ( ); 105 ::setsid ( );
106 106
107 ::signal ( SIGTERM, sigterm ); 107 ::signal ( SIGTERM, sigterm );
108 ::signal ( SIGINT, sigterm );
108 109
109 ::openlog ( "opie-login", LOG_CONS, LOG_AUTHPRIV ); 110 ::openlog ( "opie-login", LOG_CONS, LOG_AUTHPRIV );
110 ::atexit ( exit_closelog ); 111 ::atexit ( exit_closelog );
111 112
112 while ( true ) { 113 while ( true ) {
113 pid_t child = ::fork ( ); 114 pid_t child = ::fork ( );
114 115
115 if ( child < 0 ) { 116 if ( child < 0 ) {
116 ::syslog ( LOG_ERR, "Could not fork GUI process\n" ); 117 ::syslog ( LOG_ERR, "Could not fork GUI process\n" );
117 break; 118 break;
118 } 119 }
119 else if ( child > 0 ) { 120 else if ( child > 0 ) {
120 int status = 0; 121 int status = 0;
121 time_t started = ::time ( 0 ); 122 time_t started = ::time ( 0 );
122 123
123 while ( ::waitpid ( child, &status, 0 ) < 0 ) { } 124 while ( ::waitpid ( child, &status, 0 ) < 0 ) { }
124 125
126 LoginApplication::logout ( );
127
125 if (( ::time ( 0 ) - started ) < 3 ) { 128 if (( ::time ( 0 ) - started ) < 3 ) {
126 if ( autolog ) { 129 if ( autolog ) {
127 ::syslog ( LOG_ERR, "Respawning too fast -- disabling auto-login\n" ); 130 ::syslog ( LOG_ERR, "Respawning too fast -- disabling auto-login\n" );
128 autolog = 0; 131 autolog = 0;
129 } 132 }
130 else { 133 else {
131 ::syslog ( LOG_ERR, "Respawning too fast -- going down\n" ); 134 ::syslog ( LOG_ERR, "Respawning too fast -- going down\n" );
132 break; 135 break;
133 } 136 }
134 } 137 }
135 int killedbysig = 0; 138 int killedbysig = 0;
136 139
137 if ( WIFSIGNALED( status )) { 140 if ( WIFSIGNALED( status )) {
138 switch ( WTERMSIG( status )) { 141 switch ( WTERMSIG( status )) {
139 case SIGINT : 142 case SIGINT :
140 case SIGTERM: 143 case SIGTERM:
141 case SIGKILL: 144 case SIGKILL:
142 break; 145 break;
143 146
144 default : 147 default :
145 killedbysig = WTERMSIG( status ); 148 killedbysig = WTERMSIG( status );
146 break; 149 break;
147 } 150 }
148 } 151 }
149 if ( killedbysig ) { // qpe was killed by an uncaught signal 152 if ( killedbysig ) { // qpe was killed by an uncaught signal
150 qApp = 0; 153 qApp = 0;
154
155 ::syslog ( LOG_ERR, "Opie was killed by a signal #%d", killedbysig );
151 156
152 QWSServer::setDesktopBackground ( QImage ( )); 157 QWSServer::setDesktopBackground ( QImage ( ));
153 QApplication *app = new QApplication ( argc, argv, QApplication::GuiServer ); 158 QApplication *app = new QApplication ( argc, argv, QApplication::GuiServer );
154 app-> setFont ( QFont ( "Helvetica", 10 )); 159 app-> setFont ( QFont ( "Helvetica", 10 ));
155 app-> setStyle ( new QPEStyle ( )); 160 app-> setStyle ( new QPEStyle ( ));
156 161
157 const char *sig = ::strsignal ( killedbysig ); 162 const char *sig = ::strsignal ( killedbysig );
158 QLabel *l = new QLabel ( 0, "sig", Qt::WStyle_Customize | Qt::WStyle_NoBorder | Qt::WStyle_Tool ); 163 QLabel *l = new QLabel ( 0, "sig", Qt::WStyle_Customize | Qt::WStyle_NoBorder | Qt::WStyle_Tool );
159 l-> setText ( LoginWindowImpl::tr( "OPIE was terminated\nby an uncaught signal\n(%1)\n" ). arg ( sig )); 164 l-> setText ( LoginWindowImpl::tr( "OPIE was terminated\nby an uncaught signal\n(%1)\n" ). arg ( sig ));
160 l-> setAlignment ( Qt::AlignCenter ); 165 l-> setAlignment ( Qt::AlignCenter );
161 l-> move ( 0, 0 ); 166 l-> move ( 0, 0 );
162 l-> resize ( app-> desktop ( )-> width ( ), app-> desktop ( )-> height ( )); 167 l-> resize ( app-> desktop ( )-> width ( ), app-> desktop ( )-> height ( ));
163 l-> show ( ); 168 l-> show ( );
164 QTimer::singleShot ( 3000, app, SLOT( quit ( ))); 169 QTimer::singleShot ( 3000, app, SLOT( quit ( )));
165 app-> exec ( ); 170 app-> exec ( );
166 delete app; 171 delete app;
167 qApp = 0; 172 qApp = 0;
168 } 173 }
169 } 174 }
170 else { 175 else {
171 if ( !autolog ) { 176 if ( !autolog ) {
172 Config cfg ( "opie-login" ); 177 Config cfg ( "opie-login" );
173 cfg. setGroup ( "General" ); 178 cfg. setGroup ( "General" );
174 QString user = cfg. readEntry ( "AutoLogin" ); 179 QString user = cfg. readEntry ( "AutoLogin" );
175 180
176 if ( !user. isEmpty ( )) 181 if ( !user. isEmpty ( ))
177 autolog = ::strdup ( user. latin1 ( )); 182 autolog = ::strdup ( user. latin1 ( ));
178 } 183 }
179 184
180 if ( autolog ) { 185 if ( autolog ) {
181 LoginApplication::setLoginAs ( autolog ); 186 LoginApplication::setLoginAs ( autolog );
182 187
183 if ( LoginApplication::changeIdentity ( )) 188 if ( LoginApplication::changeIdentity ( ))
184 ::exit ( LoginApplication::login ( )); 189 ::exit ( LoginApplication::login ( ));
185 else 190 else
186 ::exit ( 0 ); 191 ::exit ( 0 );
187 } 192 }
188 else 193 else
189 ::exit ( login_main ( argc, argv, ppid )); 194 ::exit ( login_main ( argc, argv, ppid ));
190 } 195 }
191 } 196 }
192 return 0; 197 return 0;
193} 198}
194 199
195void sigterm ( int /*sig*/ ) 200void sigterm ( int /*sig*/ )
196{ 201{
197 ::exit ( 0 ); 202 ::exit ( 0 );
198} 203}
199 204
200 205
201void exit_closelog ( ) 206void exit_closelog ( )
202{ 207{
203 ::closelog ( ); 208 ::closelog ( );
204} 209}
205 210
206 211
207class LoginScreenSaver : public QWSScreenSaver 212class LoginScreenSaver : public QWSScreenSaver
208{ 213{
209public: 214public:
210 LoginScreenSaver ( ) 215 LoginScreenSaver ( )
211 { 216 {
212 m_lcd_status = true; 217 m_lcd_status = true;
213 218
214 m_backlight_bright = -1; 219 m_backlight_bright = -1;
215 m_backlight_forcedoff = false; 220 m_backlight_forcedoff = false;
216 221
217 // Make sure the LCD is in fact on, (if opie was killed while the LCD is off it would still be off) 222 // Make sure the LCD is in fact on, (if opie was killed while the LCD is off it would still be off)
218 ODevice::inst ( )-> setDisplayStatus ( true ); 223 ODevice::inst ( )-> setDisplayStatus ( true );
219 } 224 }
220 void restore() 225 void restore()
221 { 226 {
222 if ( !m_lcd_status ) // We must have turned it off 227 if ( !m_lcd_status ) // We must have turned it off
223 ODevice::inst ( ) -> setDisplayStatus ( true ); 228 ODevice::inst ( ) -> setDisplayStatus ( true );
224 229
225 setBacklight ( -3 ); 230 setBacklight ( -3 );
226 } 231 }
227 bool save( int level ) 232 bool save( int level )
228 { 233 {
229 switch ( level ) { 234 switch ( level ) {
230 case 0: 235 case 0:
231 if ( backlight() > 1 ) 236 if ( backlight() > 1 )
232 setBacklight( 1 ); // lowest non-off 237 setBacklight( 1 ); // lowest non-off
233 return true; 238 return true;
234 break; 239 break;
235 case 1: 240 case 1:
236 setBacklight( 0 ); // off 241 setBacklight( 0 ); // off
237 return true; 242 return true;
238 break; 243 break;
239 case 2: 244 case 2:
240 // We're going to suspend the whole machine 245 // We're going to suspend the whole machine
241 if ( PowerStatusManager::readStatus().acStatus() != PowerStatus::Online ) { 246 if ( PowerStatusManager::readStatus().acStatus() != PowerStatus::Online ) {
242 QWSServer::sendKeyEvent( 0xffff, Qt::Key_F34, FALSE, TRUE, FALSE ); 247 QWSServer::sendKeyEvent( 0xffff, Qt::Key_F34, FALSE, TRUE, FALSE );
243 return true; 248 return true;
244 } 249 }
245 break; 250 break;
246 } 251 }
247 return false; 252 return false;
248 } 253 }
249 254
250private: 255private:
251public: 256public:
252 void setIntervals( int i1 = 30, int i2 = 20, int i3 = 60 ) 257 void setIntervals( int i1 = 30, int i2 = 20, int i3 = 60 )
253 { 258 {
254 int v [4]; 259 int v [4];
255 260
256 v [ 0 ] = QMAX( 1000 * i1, 100 ); 261 v [ 0 ] = QMAX( 1000 * i1, 100 );
257 v [ 1 ] = QMAX( 1000 * i2, 100 ); 262 v [ 1 ] = QMAX( 1000 * i2, 100 );
258 v [ 2 ] = QMAX( 1000 * i3, 100 ); 263 v [ 2 ] = QMAX( 1000 * i3, 100 );
259 v [ 3 ] = 0; 264 v [ 3 ] = 0;
260 265
261 if ( !i1 && !i2 && !i3 ) 266 if ( !i1 && !i2 && !i3 )
262 QWSServer::setScreenSaverInterval ( 0 ); 267 QWSServer::setScreenSaverInterval ( 0 );
263 else 268 else
264 QWSServer::setScreenSaverIntervals ( v ); 269 QWSServer::setScreenSaverIntervals ( v );
265 } 270 }
266 271
267 int backlight ( ) 272 int backlight ( )
268 { 273 {
269 if ( m_backlight_bright == -1 ) 274 if ( m_backlight_bright == -1 )
270 m_backlight_bright = 255; 275 m_backlight_bright = 255;
271 276
272 return m_backlight_bright; 277 return m_backlight_bright;
273 } 278 }
274 279
275 void setBacklight ( int bright ) 280 void setBacklight ( int bright )
276 { 281 {
277 if ( bright == -3 ) { 282 if ( bright == -3 ) {
278 // Forced on 283 // Forced on
279 m_backlight_forcedoff = false; 284 m_backlight_forcedoff = false;
280 bright = -1; 285 bright = -1;
281 } 286 }
282 if ( m_backlight_forcedoff && bright != -2 ) 287 if ( m_backlight_forcedoff && bright != -2 )
283 return ; 288 return ;
284 if ( bright == -2 ) { 289 if ( bright == -2 ) {
285 // Toggle between off and on 290 // Toggle between off and on
286 bright = m_backlight_bright ? 0 : -1; 291 bright = m_backlight_bright ? 0 : -1;
287 m_backlight_forcedoff = !bright; 292 m_backlight_forcedoff = !bright;
288 } 293 }
289 294
290 m_backlight_bright = bright; 295 m_backlight_bright = bright;
291 296
292 bright = backlight ( ); 297 bright = backlight ( );
293 ODevice::inst ( ) -> setDisplayBrightness ( bright ); 298 ODevice::inst ( ) -> setDisplayBrightness ( bright );
294 299
295 m_backlight_bright = bright; 300 m_backlight_bright = bright;
296 } 301 }
297 302
298private: 303private:
299 bool m_lcd_status; 304 bool m_lcd_status;
300 305
301 int m_backlight_bright; 306 int m_backlight_bright;
302 bool m_backlight_forcedoff; 307 bool m_backlight_forcedoff;
303}; 308};
304 309
305 310
311namespace Opie { extern int force_appearance; } // HACK to get around the force-style setting
306 312
307 313
308int login_main ( int argc, char **argv, pid_t ppid ) 314int login_main ( int argc, char **argv, pid_t ppid )
309{ 315{
310 QWSServer::setDesktopBackground( QImage() ); 316 QWSServer::setDesktopBackground( QImage() );
311 LoginApplication *app = new LoginApplication ( argc, argv, ppid ); 317 LoginApplication *app = new LoginApplication ( argc, argv, ppid );
312 318
319 Opie::force_appearance = 0;
320
313 app-> setFont ( QFont ( "Helvetica", 10 )); 321 app-> setFont ( QFont ( "Helvetica", 10 ));
314 app-> setStyle ( new QPEStyle ( )); 322 app-> setStyle ( new QPEStyle ( ));
315 323
316 ODevice::inst ( )-> setSoftSuspend ( true ); 324 ODevice::inst ( )-> setSoftSuspend ( true );
317 325
318#if defined(QT_QWS_CASSIOPEIA) || defined(QT_QWS_IPAQ) || defined(QT_QWS_EBX) 326#if defined(QT_QWS_CASSIOPEIA) || defined(QT_QWS_IPAQ) || defined(QT_QWS_EBX)
319 if ( !QFile::exists ( "/etc/pointercal" )) { 327 if ( !QFile::exists ( "/etc/pointercal" )) {
320 // Make sure calibration widget starts on top. 328 // Make sure calibration widget starts on top.
321 Calibrate *cal = new Calibrate; 329 Calibrate *cal = new Calibrate;
322 cal-> exec ( ); 330 cal-> exec ( );
323 delete cal; 331 delete cal;
324 } 332 }
325#endif 333#endif
326 334
327 LoginScreenSaver *saver = new LoginScreenSaver; 335 LoginScreenSaver *saver = new LoginScreenSaver;
328 336
329 saver-> setIntervals ( ); 337 saver-> setIntervals ( );
330 QWSServer::setScreenSaver ( saver ); 338 QWSServer::setScreenSaver ( saver );
331 saver-> restore ( ); 339 saver-> restore ( );
332 340
333 341
334 LoginWindowImpl *lw = new LoginWindowImpl ( ); 342 LoginWindowImpl *lw = new LoginWindowImpl ( );
335 app-> setMainWidget ( lw ); 343 app-> setMainWidget ( lw );
336 lw-> setGeometry ( 0, 0, app-> desktop ( )-> width ( ), app-> desktop ( )-> height ( )); 344 lw-> setGeometry ( 0, 0, app-> desktop ( )-> width ( ), app-> desktop ( )-> height ( ));
337 lw-> show ( ); 345 lw-> show ( );
338 346
339 int rc = app-> exec ( ); 347 int rc = app-> exec ( );
340 348
341 ODevice::inst ( )-> setSoftSuspend ( false ); 349 ODevice::inst ( )-> setSoftSuspend ( false );
342 350
343 if ( app-> loginAs ( )) { 351 if ( app-> loginAs ( )) {
344 if ( app-> changeIdentity ( )) { 352 if ( app-> changeIdentity ( )) {
345 app-> login ( ); 353 app-> login ( );
346 354
347 // if login succeeds, it never comes back 355 // if login succeeds, it never comes back
348 356
349 QMessageBox::critical ( 0, LoginWindowImpl::tr( "Failure" ), LoginWindowImpl::tr( "Could not start OPIE." )); 357 QMessageBox::critical ( 0, LoginWindowImpl::tr( "Failure" ), LoginWindowImpl::tr( "Could not start OPIE." ));
350 rc = 1; 358 rc = 1;
351 } 359 }
352 else { 360 else {
353 QMessageBox::critical ( 0, LoginWindowImpl::tr( "Failure" ), LoginWindowImpl::tr( "Could not switch to new user identity" )); 361 QMessageBox::critical ( 0, LoginWindowImpl::tr( "Failure" ), LoginWindowImpl::tr( "Could not switch to new user identity" ));
354 rc = 2; 362 rc = 2;
355 } 363 }
356 364
357 } 365 }
358 return rc; 366 return rc;
359} 367}
360 368