summaryrefslogtreecommitdiff
path: root/core/opie-login/loginapplication.cpp
Side-by-side diff
Diffstat (limited to 'core/opie-login/loginapplication.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--core/opie-login/loginapplication.cpp74
1 files changed, 67 insertions, 7 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
@@ -21,24 +21,26 @@
  -_. . .   )=.  = see the file COPYING. If not, write to the
    --        :-=` Free Software Foundation, Inc.,
59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include <pwd.h>
#include <grp.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
#ifdef USEPAM
extern "C" {
#include <security/pam_appl.h>
}
#else
#include <crypt.h>
#include <shadow.h>
#endif
#include "loginapplication.h"
@@ -149,53 +151,111 @@ bool LoginApplication::checkPassword ( const char *user, const char *pass )
bool LoginApplication::changeIdentity ( )
{
const char *DEFAULT_LOGIN_PATH = "/bin:/usr/bin";
const char *DEFAULT_ROOT_LOGIN_PATH = "/usr/sbin:/bin:/usr/bin:/sbin";
if ( !s_username )
return false;
struct passwd *pw = ::getpwnam ( s_username );
if ( !pw )
return false;
+ // we are still root at this point - try to run the pre-session script
+ if ( !runRootScript ( "OPIEDIR", "share/opie-login/pre-session", s_username ))
+ qWarning ( "failed to run $OPIEDIR/share/opie-login/pre-session" );
+
bool fail = false;
fail |= ( ::initgroups ( pw-> pw_name, pw-> pw_gid ));
::endgrent ( );
fail |= ( ::setgid ( pw-> pw_gid ));
fail |= ( ::setuid ( pw-> pw_uid ));
fail |= ( ::chdir ( pw-> pw_dir ) && ::chdir ( "/" ));
fail |= ( ::setenv ( "HOME", pw-> pw_dir, 1 ));
fail |= ( ::setenv ( "SHELL", pw-> pw_shell, 1 ));
fail |= ( ::setenv ( "USER", pw-> pw_name, 1 ));
fail |= ( ::setenv ( "LOGNAME", pw-> pw_name, 1 ));
fail |= ( ::setenv ( "PATH", ( pw-> pw_uid ? DEFAULT_LOGIN_PATH : DEFAULT_ROOT_LOGIN_PATH ), 1 ));
return !fail;
}
bool LoginApplication::login ( )
{
- char *opie = ::getenv ( "OPIEDIR" );
- char *arg = new char [::strlen ( opie ) + 8 + 1];
+ execUserScript ( "HOME", ".opie-session" );
+ execUserScript ( "OPIEDIR", "share/opie-login/opie-session" );
+ execUserScript ( "OPIEDIR", "bin/qpe" );
+
+ qWarning ( "failed to start an Opie session" );
+ return false;
+}
+
+void LoginApplication::logout ( )
+{
+ // we are now root again - try to run the post-session script
+ if ( !runRootScript ( "OPIEDIR", "share/opie-login/post-session" ))
+ qWarning ( "failed to run $OPIEDIR/scripts/post-session" );
+}
- ::strcpy ( arg, opie );
- ::strcat ( arg, "/bin/qpe" );
- // start qpe via a login shell
- ::execl ( "/bin/sh", "-sh", "-c", arg, 0 );
+static char *buildarg ( const char *base, const char *script )
+{
+ const char *dir = base ? ::getenv ( base ) : "/";
+ char *arg = new char [::strlen ( dir ) + ::strlen ( script ) + 2];
- return false;
+ ::strcpy ( arg, dir );
+ ::strcat ( arg, "/" );
+ ::strcat ( arg, script );
+
+ return arg;
+}
+
+bool LoginApplication::runRootScript ( const char *base, const char *script, const char *param )
+{
+ bool res = false;
+ char *arg = buildarg ( base, script );
+
+ struct stat st;
+ if (( ::stat ( arg, &st ) == 0 ) && ( st. st_uid == 0 )) {
+ pid_t child = ::fork ( );
+
+ if ( child == 0 ) {
+ ::execl ( "/bin/sh", "-sh", arg, param, 0 );
+ ::_exit ( -1 );
+ }
+ else if ( child > 0 ) {
+ int status = 0;
+
+ while ( ::waitpid ( child, &status, 0 ) < 0 ) { }
+ res = ( WIFEXITED( status )) && ( WEXITSTATUS( status ) == 0 );
+ }
+ }
+
+ delete [] arg;
+ return res;
+}
+
+void LoginApplication::execUserScript ( const char *base, const char *script )
+{
+ char *arg = buildarg ( base, script );
+
+ struct stat st;
+ if ( ::stat ( arg, &st ) == 0 ) {
+ if ( st. st_mode & S_IXUSR )
+ ::execl ( "/bin/sh", "-sh", "-c", arg, 0 );
+ else
+ ::execl ( "/bin/sh", "-sh", arg, 0 );
+ }
}
const char *LoginApplication::loginAs ( )
{
return s_username;
}
void LoginApplication::setLoginAs ( const char *name )
{
s_username = name;
}