summaryrefslogtreecommitdiff
authorsandman <sandman>2002-10-14 00:59:28 (UTC)
committer sandman <sandman>2002-10-14 00:59:28 (UTC)
commit62c946c5a92ab11b5ad9495ff0bab158d38bce48 (patch) (unidiff)
tree01375a50aace755e808eef3103d3c4395530b4f1
parent72c07a1db3bad19fa227fc6fb482afe517d18095 (diff)
downloadopie-62c946c5a92ab11b5ad9495ff0bab158d38bce48.zip
opie-62c946c5a92ab11b5ad9495ff0bab158d38bce48.tar.gz
opie-62c946c5a92ab11b5ad9495ff0bab158d38bce48.tar.bz2
- last login name is saved
- wait image should be displayed right now - the qApp object is destroyed before the launcher is started -- this should prevent some semaphore permission problems - added a (very basic) crash handler - added a simple "respawned too fast" detection in case of qt/e fb problems - if opie-login is started with -a <user> or --autologin <user> it doesn't prompt for a username/password - instead it loads qpe directly using the specified user account So even if you are not running multiuser, you should now start qpe with: opie-login --autologin=root
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--core/opie-login/loginapplication.cpp193
-rw-r--r--core/opie-login/loginapplication.h40
-rw-r--r--core/opie-login/loginwindowimpl.cpp270
-rw-r--r--core/opie-login/main.cpp126
-rw-r--r--core/opie-login/opie-login.pro2
5 files changed, 398 insertions, 233 deletions
diff --git a/core/opie-login/loginapplication.cpp b/core/opie-login/loginapplication.cpp
new file mode 100644
index 0000000..cd58c47
--- a/dev/null
+++ b/core/opie-login/loginapplication.cpp
@@ -0,0 +1,193 @@
1#include <pwd.h>
2#include <grp.h>
3#include <unistd.h>
4#include <stdlib.h>
5#include <signal.h>
6
7#ifdef USEPAM
8extern "C" {
9#include <security/pam_appl.h>
10}
11#else
12#include <crypt.h>
13#include <shadow.h>
14#endif
15
16#include "loginapplication.h"
17
18LoginApplication *lApp;
19
20LoginApplication::LoginApplication ( int &argc, char **argv )
21 : QPEApplication ( argc, argv, GuiServer )
22{
23 lApp = this;
24}
25
26const char *LoginApplication::s_username = 0;
27
28#ifdef USEPAM
29
30const char *LoginApplication::s_pam_password = 0;
31
32int LoginApplication::pam_helper ( int num_msg, const struct pam_message **msg, struct pam_response **resp, void * )
33{
34 int replies = 0;
35 struct pam_response *reply = 0;
36 int size = sizeof( struct pam_response );
37
38 for ( int i = 0; i < num_msg; i++ ) {
39 switch ( msg [i]-> msg_style ) {
40 case PAM_PROMPT_ECHO_ON: // user name given to PAM already
41 return PAM_CONV_ERR;
42
43 case PAM_PROMPT_ECHO_OFF: // wants password
44 reply = (struct pam_response *) ::realloc ( reply, size );
45 if ( !reply )
46 return PAM_CONV_ERR;
47 size += sizeof( struct pam_response );
48
49 reply [replies]. resp_retcode = PAM_SUCCESS;
50 reply [replies]. resp = ::strdup ( s_pam_password );
51 replies++; // PAM frees resp
52 break;
53
54 case PAM_TEXT_INFO:
55 break;
56
57 default:
58 /* unknown or PAM_ERROR_MSG */
59 if ( reply )
60 ::free ( reply );
61 return PAM_CONV_ERR;
62 }
63 }
64 if ( reply )
65 *resp = reply;
66 return PAM_SUCCESS;
67}
68
69
70bool LoginApplication::checkPassword ( const char *user, const char *pass )
71{
72 static struct pam_conv conv = { &LoginApplication::pam_helper, 0 };
73
74 int pam_error;
75 pam_handle_t *pamh = 0;
76
77 pam_error = ::pam_start( "xdm", user, &conv, &pamh );
78 if ( pam_error == PAM_SUCCESS ) {
79 s_pam_password = pass;
80 pam_error = ::pam_authenticate ( pamh, 0 );
81 s_pam_password = 0;
82 }
83 ::pam_end ( pamh, pam_error );
84 return ( pam_error == PAM_SUCCESS );
85}
86
87#else
88
89bool LoginApplication::checkPassword ( const char *user, const char *pass )
90{
91 char *encrypted, *correct;
92 struct passwd *pw;
93
94 if ( !user || !pass )
95 return false;
96
97 pw = ::getpwnam ( user );
98
99 if ( !pw )
100 return false;
101
102 if (( ::strcmp ( pw-> pw_passwd, "x" ) == 0 ) || ( ::strcmp ( pw-> pw_passwd, "*" ) == 0 )) {
103 struct spwd *sp = ::getspnam ( pw-> pw_name );
104
105 if ( !sp )
106 return false;
107
108 correct = sp-> sp_pwdp;
109 }
110 else
111 correct = pw-> pw_passwd;
112
113 if ( correct == 0 || correct[0] == '\0' )
114 return true;
115
116 encrypted = ::crypt ( pass, correct );
117 return ( ::strcmp ( encrypted, correct ) == 0 );
118}
119
120#endif
121
122bool LoginApplication::changeIdentity ( )
123{
124 const char *DEFAULT_LOGIN_PATH = "/bin:/usr/bin";
125 const char *DEFAULT_ROOT_LOGIN_PATH = "/usr/sbin:/bin:/usr/bin:/sbin";
126
127 if ( !s_username )
128 return false;
129 struct passwd *pw = ::getpwnam ( s_username );
130 if ( !pw )
131 return false;
132
133 bool fail = false;
134 fail |= ( ::initgroups ( pw-> pw_name, pw-> pw_gid ));
135 ::endgrent ( );
136 fail |= ( ::setgid ( pw-> pw_gid ));
137 fail |= ( ::setuid ( pw-> pw_uid ));
138
139 fail |= ( ::chdir ( pw-> pw_dir ) && ::chdir ( "/" ));
140
141 fail |= ( ::setenv ( "HOME", pw-> pw_dir, 1 ));
142 fail |= ( ::setenv ( "SHELL", pw-> pw_shell, 1 ));
143 fail |= ( ::setenv ( "USER", pw-> pw_name, 1 ));
144 fail |= ( ::setenv ( "LOGNAME", pw-> pw_name, 1 ));
145 fail |= ( ::setenv ( "PATH", ( pw-> pw_uid ? DEFAULT_LOGIN_PATH : DEFAULT_ROOT_LOGIN_PATH ), 1 ));
146
147 return !fail;
148}
149
150bool LoginApplication::login ( )
151{
152 char *opie = ::getenv ( "OPIEDIR" );
153 char *arg = new char [::strlen ( opie ) + 8 + 1];
154
155 ::strcpy ( arg, opie );
156 ::strcat ( arg, "/bin/qpe" );
157
158 // start qpe via a login shell
159 ::execl ( "/bin/sh", "-sh", "-c", arg, 0 );
160
161 return false;
162}
163
164const char *LoginApplication::loginAs ( )
165{
166 return s_username;
167}
168
169void LoginApplication::setLoginAs ( const char *name )
170{
171 s_username = name;
172}
173
174QStringList LoginApplication::allUsers ( )
175{
176 struct passwd *pwd;
177 QStringList sl;
178
179 while (( pwd = ::getpwent ( ))) {
180 if (( pwd-> pw_uid == 0 ) || ( pwd-> pw_uid >= 500 && pwd-> pw_uid < 65534 ))
181 sl << QString ( pwd-> pw_name );
182 }
183
184 ::endpwent ( );
185
186 return sl;
187}
188
189void LoginApplication::quitToConsole ( )
190{
191 QPEApplication::quit ( );
192 ::kill ( ::getppid ( ), SIGTERM );
193}
diff --git a/core/opie-login/loginapplication.h b/core/opie-login/loginapplication.h
new file mode 100644
index 0000000..a709c5b
--- a/dev/null
+++ b/core/opie-login/loginapplication.h
@@ -0,0 +1,40 @@
1#ifndef __OPIE_LOGINAPPLICATION_H__
2#define __OPIE_LOGINAPPLICATION_H__
3
4#include <qstringlist.h>
5
6#include <qpe/qpeapplication.h>
7
8#ifdef USEPAM
9struct pam_message;
10struct pam_response;
11#endif
12
13class LoginApplication : public QPEApplication {
14public:
15 LoginApplication ( int &argc, char **argv );
16
17 static bool checkPassword ( const char *user, const char *password );
18
19 static const char *loginAs ( );
20 static void setLoginAs ( const char *user );
21
22 static bool changeIdentity ( );
23 static bool login ( );
24
25 static QStringList allUsers ( );
26
27 void quitToConsole ( );
28
29private:
30 static const char *s_username;
31
32#ifdef USEPAM
33 static int pam_helper ( int num_msg, const struct pam_message **msg, struct pam_response **resp, void * );
34 static const char *s_pam_password;
35#endif
36};
37
38extern LoginApplication *lApp;
39
40#endif
diff --git a/core/opie-login/loginwindowimpl.cpp b/core/opie-login/loginwindowimpl.cpp
index c59338f..3694513 100644
--- a/core/opie-login/loginwindowimpl.cpp
+++ b/core/opie-login/loginwindowimpl.cpp
@@ -8,37 +8,25 @@
8#include <qpixmap.h> 8#include <qpixmap.h>
9#include <qlabel.h> 9#include <qlabel.h>
10#include <qpopupmenu.h> 10#include <qpopupmenu.h>
11#include <qmessagebox.h> 11#include <qmessagebox.h>
12#include <qimage.h> 12#include <qimage.h>
13 13
14#include <qpe/resource.h> 14#include <qpe/resource.h>
15#include <qpe/qcopenvelope_qws.h> 15#include <qpe/qcopenvelope_qws.h>
16#include <qpe/config.h>
16 17
17#include <opie/odevice.h> 18#include <opie/odevice.h>
18 19
19#include <stdio.h> 20#include <stdio.h>
20
21#include <pwd.h>
22#include <grp.h>
23#include <unistd.h>
24#include <stdlib.h> 21#include <stdlib.h>
25#include <signal.h>
26
27#ifdef USEPAM
28extern "C" {
29#include <security/pam_appl.h>
30}
31#else
32#include <crypt.h>
33#include <shadow.h>
34#endif
35 22
36#include "loginwindowimpl.h" 23#include "loginwindowimpl.h"
24#include "loginapplication.h"
37#include "inputmethods.h" 25#include "inputmethods.h"
38 26
39using namespace Opie; 27using namespace Opie;
40 28
41 29
42LoginWindowImpl::LoginWindowImpl ( ) : LoginWindow ( 0, "LOGIN-WINDOW", WStyle_Customize | WStyle_NoBorder | WDestructiveClose ) 30LoginWindowImpl::LoginWindowImpl ( ) : LoginWindow ( 0, "LOGIN-WINDOW", WStyle_Customize | WStyle_NoBorder | WDestructiveClose )
43{ 31{
44 QPopupMenu *pop = new QPopupMenu ( this ); 32 QPopupMenu *pop = new QPopupMenu ( this );
@@ -49,27 +37,34 @@ LoginWindowImpl::LoginWindowImpl ( ) : LoginWindow ( 0, "LOGIN-WINDOW", WStyle_C
49 QHBoxLayout *lay = new QHBoxLayout ( m_taskbar, 4, 4 ); 37 QHBoxLayout *lay = new QHBoxLayout ( m_taskbar, 4, 4 );
50 m_input = new InputMethods ( m_taskbar ); 38 m_input = new InputMethods ( m_taskbar );
51 lay-> addWidget ( m_input ); 39 lay-> addWidget ( m_input );
52 lay-> addStretch ( 10 ); 40 lay-> addStretch ( 10 );
53 41
54 setActiveWindow ( ); 42 setActiveWindow ( );
55 m_password-> setFocus ( ); 43 m_password-> setFocus ( );
56 44
57 m_user-> insertStringList ( getAllUsers ( )); 45 m_user-> insertStringList ( lApp-> allUsers ( ));
58 46
59 QTimer::singleShot ( 0, this, SLOT( showIM ( ))); 47 QTimer::singleShot ( 0, this, SLOT( showIM ( )));
60 48
61 QString opiedir = ::getenv ( "OPIEDIR" ); 49 QString opiedir = ::getenv ( "OPIEDIR" );
62 QPixmap bgpix ( opiedir + "/pics/launcher/opie-background.jpg" ); 50 QPixmap bgpix ( opiedir + "/pics/launcher/opie-background.jpg" );
63 51
64 if ( !bgpix. isNull ( )) 52 if ( !bgpix. isNull ( ))
65 setBackgroundPixmap ( bgpix ); 53 setBackgroundPixmap ( bgpix );
66 54
67 m_caption-> setText ( m_caption-> text ( ) + tr( "<center>%1 %2</center>" ). arg ( ODevice::inst ( )-> systemString ( )). arg ( ODevice::inst ( )-> systemVersionString ( ))); 55 m_caption-> setText ( m_caption-> text ( ) + tr( "<center>%1 %2</center>" ). arg ( ODevice::inst ( )-> systemString ( )). arg ( ODevice::inst ( )-> systemVersionString ( )));
56
57 Config cfg ( "opie-login" );
58 cfg. setGroup ( "General" );
59 QString last = cfg. readEntry ( "LastLogin" );
60
61 if ( !last. isEmpty ( ))
62 m_user-> setEditText ( last );
68} 63}
69 64
70LoginWindowImpl::~LoginWindowImpl ( ) 65LoginWindowImpl::~LoginWindowImpl ( )
71{ 66{
72} 67}
73 68
74void LoginWindowImpl::keyPressEvent ( QKeyEvent *e ) 69void LoginWindowImpl::keyPressEvent ( QKeyEvent *e )
75{ 70{
@@ -85,261 +80,98 @@ void LoginWindowImpl::keyPressEvent ( QKeyEvent *e )
85} 80}
86 81
87 82
88void LoginWindowImpl::toggleEchoMode ( bool t ) 83void LoginWindowImpl::toggleEchoMode ( bool t )
89{ 84{
90 m_password-> setEchoMode ( t ? QLineEdit::Normal : QLineEdit::Password ); 85 m_password-> setEchoMode ( t ? QLineEdit::Normal : QLineEdit::Password );
91} 86}
92 87
93
94QStringList LoginWindowImpl::getAllUsers ( )
95{
96 struct passwd *pwd;
97 QStringList sl;
98
99 while (( pwd = ::getpwent ( ))) {
100 if (( pwd-> pw_uid == 0 ) || ( pwd-> pw_uid >= 500 && pwd-> pw_uid < 65534 ))
101 sl << QString ( pwd-> pw_name );
102 }
103
104 ::endpwent ( );
105
106 return sl;
107}
108
109void LoginWindowImpl::showIM ( ) 88void LoginWindowImpl::showIM ( )
110{ 89{
111 m_input-> showInputMethod ( ); 90 m_input-> showInputMethod ( );
112} 91}
113 92
114void LoginWindowImpl::restart ( ) 93void LoginWindowImpl::restart ( )
115{ 94{
116 qApp-> quit ( ); 95 qApp-> quit ( );
117} 96}
118 97
119void LoginWindowImpl::quit ( ) 98void LoginWindowImpl::quit ( )
120{ 99{
121 qApp-> quit ( ); 100 lApp-> quitToConsole ( );
122 ::kill ( ::getppid ( ), SIGUSR1 );
123} 101}
124 102
125void LoginWindowImpl::suspend ( ) 103void LoginWindowImpl::suspend ( )
126{ 104{
127 ODevice::inst ( )-> suspend ( ); 105 ODevice::inst ( )-> suspend ( );
128 106
129 QCopEnvelope e("QPE/System", "setBacklight(int)"); 107 QCopEnvelope e("QPE/System", "setBacklight(int)");
130 e << -3; // Force on 108 e << -3; // Force on
131} 109}
132 110
133void LoginWindowImpl::backlight ( ) 111void LoginWindowImpl::backlight ( )
134{ 112{
135 QCopEnvelope e("QPE/System", "setBacklight(int)"); 113 QCopEnvelope e("QPE/System", "setBacklight(int)");
136 e << -2; // toggle 114 e << -2; // toggle
137} 115}
138 116
139#ifdef USEPAM 117class WaitLogo : public QLabel {
140 118public:
141static const char *_PAM_SERVICE = "xdm"; 119 WaitLogo ( ) : QLabel ( 0, "wait hack!", WStyle_Customize | WStyle_NoBorder | WStyle_Tool )
142static const char *PAM_password; 120 {
143 121 QImage img = Resource::loadImage ( "launcher/new_wait" );
144typedef const struct pam_message pam_message_type; 122 QPixmap pix;
145 123 pix. convertFromImage ( img );
146static int PAM_conv( int, pam_message_type **, struct pam_response **, void * ); 124 setPixmap ( pix );
147 125 setAlignment ( AlignCenter );
148static struct pam_conv PAM_conversation = { 126 move ( 0, 0 );
149 &PAM_conv, 127 resize ( qApp-> desktop ( )-> width ( ), qApp-> desktop ( )-> height ( ));
150 NULL 128
151}; 129 m_visible = false;
152 130 show ( );
153//----------------------------------------------------------------------------
154
155static char *COPY_STRING( const char * s ) {
156 return (s) ? strdup(s) : (char *)NULL;
157}
158
159#define GET_MEM if (reply) realloc(reply, size);\
160 else reply = (struct pam_response *)malloc(size); \
161 if (!reply) return PAM_CONV_ERR; \
162 size += sizeof(struct pam_response)
163
164
165static int PAM_conv( int num_msg, pam_message_type **msg,
166 struct pam_response **resp, void *)
167{
168 int count = 0, replies = 0;
169 struct pam_response *reply = NULL;
170 int size = sizeof(struct pam_response);
171
172 for( count = 0; count < num_msg; count++ ) {
173 switch (msg[count]->msg_style) {
174 case PAM_PROMPT_ECHO_ON:
175 /* user name given to PAM already */
176 return PAM_CONV_ERR;
177
178 case PAM_PROMPT_ECHO_OFF:
179 /* wants password */
180 GET_MEM;
181 reply[replies].resp_retcode = PAM_SUCCESS;
182 reply[replies].resp = COPY_STRING(PAM_password);
183 replies++;
184 /* PAM frees resp */
185 break;
186 case PAM_TEXT_INFO:
187 break;
188 default:
189 /* unknown or PAM_ERROR_MSG */
190 if (reply) free (reply);
191 return PAM_CONV_ERR;
192 }
193 }
194 if (reply) *resp = reply;
195 return PAM_SUCCESS;
196}
197
198
199static bool pwcheck_PAM( const char *user, const char *password )
200{
201 bool pw_correct = false;
202 int pam_error;
203 int pam_return = 0;
204 pam_handle_t *pamh = 0;
205 PAM_password = password;
206
207 pam_error = pam_start( _PAM_SERVICE, user, &PAM_conversation, &pamh );
208 if( pam_error == PAM_SUCCESS ) {
209 pam_error = pam_authenticate( pamh, 0 );
210 if( pam_error == PAM_SUCCESS ) {
211 //-- password correct
212 pw_correct = true;
213 pam_return = PAM_SUCCESS;
214 } else {
215 pam_return = pam_error;
216 }
217 } else {
218 // cerr << "PAM error: " << pam_strerror( pamh, pam_error ) << endl;
219 }
220 pam_end( pamh, pam_return );
221 return pw_correct;
222}
223
224#else
225
226//----------------------------------------------------------------------------
227
228static bool pwcheck_Unix( const char *user, const char *pass )
229{
230 char *encrypted, *correct;
231 struct passwd *pw;
232
233 if ( !user || !pass )
234 return false;
235
236 pw = getpwnam ( user );
237
238 if ( !pw )
239 return false;
240
241 if (( strcmp ( pw-> pw_passwd, "x" ) == 0 ) || ( strcmp ( pw-> pw_passwd, "*" ) == 0 )) {
242 struct spwd *sp = getspnam ( pw-> pw_name );
243
244 if ( !sp )
245 return false;
246
247 correct = sp-> sp_pwdp;
248 } 131 }
249 else
250 correct = pw-> pw_passwd;
251
252 if ( correct == 0 || correct[0] == '\0' )
253 return true;
254 132
255 encrypted = crypt ( pass, correct ); 133 virtual void showEvent ( QShowEvent *e )
256 return ( strcmp ( encrypted, correct ) == 0 ); 134 {
257} 135 QLabel::showEvent ( e );
258 136 m_visible = true;
259#endif 137 }
260
261
262bool LoginWindowImpl::changeIdentity ( const char *user )
263{
264 const char *DEFAULT_LOGIN_PATH = "/bin:/usr/bin";
265 const char *DEFAULT_ROOT_LOGIN_PATH = "/usr/sbin:/bin:/usr/bin:/sbin";
266
267 bool fail = false;
268 struct passwd *pw = getpwnam ( user );
269
270 fail |= ( pw == 0 );
271 fail |= ( initgroups ( pw-> pw_name, pw-> pw_gid ));
272 endgrent ( );
273 fail |= ( setgid ( pw-> pw_gid ));
274 fail |= ( setuid ( pw-> pw_uid ));
275
276 fail |= ( chdir ( pw-> pw_dir ) && chdir ( "/" ));
277 138
278 fail |= ( setenv ( "HOME", pw-> pw_dir, 1 )); 139 virtual void paintEvent ( QPaintEvent *e )
279 fail |= ( setenv ( "SHELL", pw-> pw_shell, 1 )); 140 {
280 fail |= ( setenv ( "USER", pw-> pw_name, 1 )); 141 QLabel::paintEvent ( e );
281 fail |= ( setenv ( "LOGNAME", pw-> pw_name, 1 )); 142 if ( m_visible )
282 fail |= ( setenv ( "PATH", ( pw-> pw_uid ? DEFAULT_LOGIN_PATH : DEFAULT_ROOT_LOGIN_PATH ), 1 )); 143 qApp-> quit ( );
144 }
283 145
284 return !fail; 146private:
285} 147 bool m_visible;
148};
286 149
287void LoginWindowImpl::login ( ) 150void LoginWindowImpl::login ( )
288{ 151{
289 const char *user = ::strdup ( m_user-> currentText ( ). local8Bit ( )); 152 const char *user = ::strdup ( m_user-> currentText ( ). local8Bit ( ));
290 const char *pass = ::strdup ( m_password-> text ( ). local8Bit ( )); 153 const char *pass = ::strdup ( m_password-> text ( ). local8Bit ( ));
291 bool ok;
292 154
293 if ( !user || !user [0] ) 155 if ( !user || !user [0] )
294 return; 156 return;
295 if ( !pass ) 157 if ( !pass )
296 pass = ""; 158 pass = "";
297 159
298#if defined( USEPAM ) 160 if ( lApp-> checkPassword ( user, pass )) {
299 ok = pwcheck_PAM ( user, pass ); 161 Config cfg ( "opie-login" );
300#else 162 cfg. setGroup ( "General" );
301 ok = pwcheck_Unix ( user, pass ); 163 cfg. writeEntry ( "LastLogin", user );
302#endif 164 cfg. write ( );
303 165
304 if ( ok ) { 166 lApp-> setLoginAs ( user );
305 if ( changeIdentity ( user )) { 167
306 // Draw a big wait icon, the image can be altered in later revisions 168 // Draw a big wait icon, the image can be altered in later revisions
307 QWidget *d = QApplication::desktop ( ); 169 m_input-> hideInputMethod ( );
308 m_input-> hideInputMethod ( ); 170 new WaitLogo ( );
309 171 // WaitLogo::showEvent() calls qApp-> quit()
310 QImage img = Resource::loadImage( "launcher/new_wait" );
311 QPixmap pix;
312 pix. convertFromImage ( img );
313 QLabel *w = new QLabel ( 0, "wait hack!", WStyle_Customize | WStyle_NoBorder | WStyle_Tool );
314 w-> setPixmap ( pix );
315 w-> setAlignment ( AlignCenter );
316 w-> showMaximized ( );
317 qApp-> processEvents ( );
318
319 char *opie = ::getenv ( "OPIEDIR" );
320 char *arg = new char [::strlen ( opie ) + 8 + 1];
321
322 ::strcpy ( arg, opie );
323 ::strcat ( arg, "/bin/qpe" );
324
325 // start qpe via a login shell
326 ::execl ( "/bin/sh", "-sh", "-c", arg, 0 );
327
328 w-> hide ( );
329 delete w;
330
331 QMessageBox::critical ( this, tr( "Failure" ), tr( "Could not start OPIE\n(%1)." ). arg ( arg ));
332 delete [] arg;
333
334 restart ( );
335 }
336 else {
337 QMessageBox::critical ( this, tr( "Failure" ), tr( "Could not switch to new user identity" ));
338 restart ( );
339 }
340 } 172 }
341 else { 173 else {
342 QMessageBox::warning ( this, tr( "Wrong password" ), tr( "The given password is incorrect." )); 174 QMessageBox::warning ( this, tr( "Wrong password" ), tr( "The given password is incorrect." ));
343 m_password-> clear ( ); 175 m_password-> clear ( );
344 } 176 }
345} 177}
diff --git a/core/opie-login/main.cpp b/core/opie-login/main.cpp
index df9451d..91610af 100644
--- a/core/opie-login/main.cpp
+++ b/core/opie-login/main.cpp
@@ -1,85 +1,167 @@
1#define _GNU_SOURCE
2
3#include <sys/types.h>
4#include <time.h>
1#include <sys/time.h> 5#include <sys/time.h>
2#include <sys/resource.h> 6#include <sys/resource.h>
3#include <unistd.h> 7#include <unistd.h>
4#include <syslog.h> 8#include <syslog.h>
5#include <sys/types.h>
6#include <sys/wait.h> 9#include <sys/wait.h>
7#include <stdio.h> 10#include <stdio.h>
8#include <stdlib.h> 11#include <stdlib.h>
9#include <signal.h> 12#include <signal.h>
13#include <getopt.h>
14#include <string.h>
10 15
11#include <qpe/qpeapplication.h> 16#include <qpe/qpeapplication.h>
12#include <qpe/qcopenvelope_qws.h> 17#include <qpe/qcopenvelope_qws.h>
13#include <qpe/qpestyle.h> 18#include <qpe/qpestyle.h>
14#include <qpe/power.h> 19#include <qpe/power.h>
15 20
16#include <opie/odevice.h> 21#include <opie/odevice.h>
17 22
18#include <qwindowsystem_qws.h> 23#include <qwindowsystem_qws.h>
19#include <qfile.h> 24#include <qmessagebox.h>
25#include <qlabel.h>
26#include <qtimer.h>
20 27
28#include "loginapplication.h"
21#include "loginwindowimpl.h" 29#include "loginwindowimpl.h"
22#include "calibrate.h" 30#include "calibrate.h"
23 31
24using namespace Opie; 32using namespace Opie;
25 33
26int login_main ( int argc, char **argv ); 34int login_main ( int argc, char **argv );
27void sigusr1 ( int sig ); 35void sigterm ( int sig );
28void exit_closelog ( ); 36void exit_closelog ( );
29 37
38static struct option long_options [] = {
39 { "autologin", 1, 0, 'a' },
40 { 0, 0, 0, 0 }
41};
30 42
31 43
32int main ( int argc, char **argv ) 44int main ( int argc, char **argv )
33{ 45{
34 if ( ::geteuid ( ) != 0 ) { 46 if ( ::geteuid ( ) != 0 ) {
35 ::fprintf ( stderr, "%s can only be executed by root. (or chmod +s)", argv [0] ); 47 ::fprintf ( stderr, "%s can only be executed by root. (or chmod +s)", argv [0] );
36 return 1; 48 return 1;
37 } 49 }
50 if ( ::getuid ( ) != 0 ) // qt doesn't really like SUID and
51 ::setuid ( 0 ); // messes up things like config files
52
53 char *autolog = 0;
54 int c;
55 while (( c = ::getopt_long ( argc, argv, "a:", long_options, 0 )) != -1 ) {
56 switch ( c ) {
57 case 'a':
58 autolog = optarg;
59 break;
60 default:
61 ::fprintf ( stderr, "Usage: %s [-a|--autologin=<user>]\n", argv [0] );
62 return 2;
63 }
64 }
38 65
39 //struct rlimit rl; 66 //struct rlimit rl;
40 //::getrlimit ( RLIMIT_NOFILE, &rl ); 67 //::getrlimit ( RLIMIT_NOFILE, &rl );
41 68
42 //for ( unsigned int i = 0; i < rl. rlim_cur; i++ ) 69 //for ( unsigned int i = 0; i < rl. rlim_cur; i++ )
43 // ::close ( i ); 70 // ::close ( i );
44 71
45 ::setpgid ( 0, 0 ); 72 ::setpgid ( 0, 0 );
46 ::setsid ( ); 73 ::setsid ( );
47 74
48 ::signal ( SIGUSR1, sigusr1 ); 75 ::signal ( SIGTERM, sigterm );
49 76
50 ::openlog ( "opie-login", LOG_CONS, LOG_AUTHPRIV ); 77 ::openlog ( "opie-login", LOG_CONS, LOG_AUTHPRIV );
51 ::atexit ( exit_closelog ); 78 ::atexit ( exit_closelog );
52 79
53 while ( true ) { 80 while ( true ) {
54 pid_t child = ::fork ( ); 81 pid_t child = ::fork ( );
55 82
56 if ( child < 0 ) { 83 if ( child < 0 ) {
57 ::syslog ( LOG_ERR, "Could not fork process" ); 84 ::syslog ( LOG_ERR, "Could not fork GUI process\n" );
58 break; 85 break;
59
60 } 86 }
61 else if ( child > 0 ) { 87 else if ( child > 0 ) {
62 int status = 0; 88 int status = 0;
89 time_t started = ::time ( 0 );
63 90
64 while ( ::waitpid ( child, &status, 0 ) < 0 ) { } 91 while ( ::waitpid ( child, &status, 0 ) < 0 ) { }
92
93 if (( ::time ( 0 ) - started ) < 3 ) {
94 if ( autolog ) {
95 ::syslog ( LOG_ERR, "Respawning too fast -- disabling auto-login\n" );
96 autolog = 0;
97 }
98 else {
99 ::syslog ( LOG_ERR, "Respawning too fast -- going down\n" );
100 break;
101 }
102 }
103 int killedbysig = 0;
104
105 if ( WIFSIGNALED( status )) {
106 switch ( WTERMSIG( status )) {
107 case SIGINT :
108 case SIGTERM:
109 case SIGKILL:
110 break;
111
112 default :
113 killedbysig = WTERMSIG( status );
114 break;
115 }
116 }
117 if ( killedbysig ) { // qpe was killed by an uncaught signal
118 qApp = 0;
119
120 QWSServer::setDesktopBackground ( QImage ( ));
121 QApplication *app = new QApplication ( argc, argv, QApplication::GuiServer );
122 app-> setFont ( QFont ( "Helvetica", 10 ));
123 app-> setStyle ( new QPEStyle ( ));
124
125 const char *sig = ::strsignal ( killedbysig );
126 QLabel *l = new QLabel ( 0, "sig", Qt::WStyle_Customize | Qt::WStyle_NoBorder | Qt::WStyle_Tool );
127 l-> setText ( LoginWindowImpl::tr( "OPIE was terminated\nby an uncaught signal\n(%1)\n" ). arg ( sig ));
128 l-> setAlignment ( Qt::AlignCenter );
129 l-> move ( 0, 0 );
130 l-> resize ( app-> desktop ( )-> width ( ), app-> desktop ( )-> height ( ));
131 l-> show ( );
132 QTimer::singleShot ( 3000, app, SLOT( quit ( )));
133 app-> exec ( );
134 delete app;
135 qApp = 0;
136 }
65 } 137 }
66 else { 138 else {
67 ::exit ( login_main ( argc, argv )); 139 if ( autolog ) {
140 LoginApplication::setLoginAs ( autolog );
141
142 if ( LoginApplication::changeIdentity ( ))
143 ::exit ( LoginApplication::login ( ));
144 else
145 ::exit ( 0 );
146 }
147 else
148 ::exit ( login_main ( argc, argv ));
68 } 149 }
69 } 150 }
70 return 0; 151 return 0;
71} 152}
72 153
73void sigusr1 ( int /*sig*/ ) 154void sigterm ( int /*sig*/ )
74{ 155{
75 ::exit ( 0 ); 156 ::exit ( 0 );
76} 157}
77 158
159
78void exit_closelog ( ) 160void exit_closelog ( )
79{ 161{
80 ::closelog ( ); 162 ::closelog ( );
81} 163}
82 164
83 165
84class LoginScreenSaver : public QWSScreenSaver 166class LoginScreenSaver : public QWSScreenSaver
85{ 167{
@@ -176,23 +258,24 @@ private:
176 bool m_lcd_status; 258 bool m_lcd_status;
177 259
178 int m_backlight_bright; 260 int m_backlight_bright;
179 bool m_backlight_forcedoff; 261 bool m_backlight_forcedoff;
180}; 262};
181 263
182 264
183 265
266
184int login_main ( int argc, char **argv ) 267int login_main ( int argc, char **argv )
185{ 268{
186 QWSServer::setDesktopBackground( QImage() ); 269 QWSServer::setDesktopBackground( QImage() );
187 QPEApplication app ( argc, argv, QApplication::GuiServer ); 270 LoginApplication *app = new LoginApplication ( argc, argv );
188 271
189 app. setFont ( QFont ( "Helvetica", 10 )); 272 app-> setFont ( QFont ( "Helvetica", 10 ));
190 app. setStyle ( new QPEStyle ( )); 273 app-> setStyle ( new QPEStyle ( ));
191 274
192 ODevice::inst ( )-> setSoftSuspend ( true ); 275 ODevice::inst ( )-> setSoftSuspend ( true );
193 276
194#if defined(QT_QWS_CASSIOPEIA) || defined(QT_QWS_IPAQ) || defined(QT_QWS_EBX) 277#if defined(QT_QWS_CASSIOPEIA) || defined(QT_QWS_IPAQ) || defined(QT_QWS_EBX)
195 if ( !QFile::exists ( "/etc/pointercal" )) { 278 if ( !QFile::exists ( "/etc/pointercal" )) {
196 // Make sure calibration widget starts on top. 279 // Make sure calibration widget starts on top.
197 Calibrate *cal = new Calibrate; 280 Calibrate *cal = new Calibrate;
198 cal-> exec ( ); 281 cal-> exec ( );
@@ -203,19 +286,34 @@ int login_main ( int argc, char **argv )
203 LoginScreenSaver *saver = new LoginScreenSaver; 286 LoginScreenSaver *saver = new LoginScreenSaver;
204 287
205 saver-> setIntervals ( ); 288 saver-> setIntervals ( );
206 QWSServer::setScreenSaver ( saver ); 289 QWSServer::setScreenSaver ( saver );
207 saver-> restore ( ); 290 saver-> restore ( );
208 291
209 292
210 LoginWindowImpl *lw = new LoginWindowImpl ( ); 293 LoginWindowImpl *lw = new LoginWindowImpl ( );
211 app. setMainWidget ( lw ); 294 app-> setMainWidget ( lw );
212 lw-> setGeometry ( 0, 0, app. desktop ( )-> width ( ), app. desktop ( )-> height ( )); 295 lw-> setGeometry ( 0, 0, app-> desktop ( )-> width ( ), app-> desktop ( )-> height ( ));
213 lw-> show ( ); 296 lw-> show ( );
214 297
215 int rc = app. exec ( ); 298 int rc = app-> exec ( );
216 299
217 ODevice::inst ( )-> setSoftSuspend ( false ); 300 ODevice::inst ( )-> setSoftSuspend ( false );
218 301
302 if ( app-> loginAs ( )) {
303 if ( app-> changeIdentity ( )) {
304 app-> login ( );
305
306 // if login succeeds, it never comes back
307
308 QMessageBox::critical ( 0, LoginWindowImpl::tr( "Failure" ), LoginWindowImpl::tr( "Could not start OPIE." ));
309 rc = 1;
310 }
311 else {
312 QMessageBox::critical ( 0, LoginWindowImpl::tr( "Failure" ), LoginWindowImpl::tr( "Could not switch to new user identity" ));
313 rc = 2;
314 }
315
316 }
219 return rc; 317 return rc;
220} 318}
221 319
diff --git a/core/opie-login/opie-login.pro b/core/opie-login/opie-login.pro
index 35c1ed0..45b9a7a 100644
--- a/core/opie-login/opie-login.pro
+++ b/core/opie-login/opie-login.pro
@@ -1,16 +1,18 @@
1TEMPLATE = app 1TEMPLATE = app
2CONFIG = qt warn_on debug usepam 2CONFIG = qt warn_on debug usepam
3 3
4HEADERS = loginwindowimpl.h \ 4HEADERS = loginwindowimpl.h \
5 loginapplication.h \
5 ../launcher/inputmethods.h \ 6 ../launcher/inputmethods.h \
6 ../apps/calibrate/calibrate.h 7 ../apps/calibrate/calibrate.h
7 8
8SOURCES = loginwindowimpl.cpp \ 9SOURCES = loginwindowimpl.cpp \
10 loginapplication.cpp \
9 ../launcher/inputmethods.cpp \ 11 ../launcher/inputmethods.cpp \
10 ../apps/calibrate/calibrate.cpp \ 12 ../apps/calibrate/calibrate.cpp \
11 main.cpp 13 main.cpp
12 14
13INTERFACES = loginwindow.ui 15INTERFACES = loginwindow.ui
14 16
15INCLUDEPATH += $(OPIEDIR)/include ../launcher ../apps/calibrate 17INCLUDEPATH += $(OPIEDIR)/include ../launcher ../apps/calibrate
16DEPENDPATH += $(OPIEDIR)/include ../launcher ../apps/calibrate 18DEPENDPATH += $(OPIEDIR)/include ../launcher ../apps/calibrate