示例#1
0
int main(int argc, char *argv[])
{
    // FIXME: this can be considered a poor man's solution, as it's not
    // directly obvious to a gui user. :)
    // anyway, i vote against removing it even when we have a proper gui
    // implementation.  -- ossi
    const char *duser = ::getenv("ADMIN_ACCOUNT");
    if (duser && duser[0])
        options[3].def = duser;

    KAboutData aboutData("kdesu", I18N_NOOP("KDE su"),
            Version, I18N_NOOP("Runs a program with elevated privileges."),
            KAboutData::License_Artistic,
            "Copyright (c) 1998-2000 Geert Jansen, Pietro Iglio");
    aboutData.addAuthor("Geert Jansen", I18N_NOOP("Maintainer"),
            "*****@*****.**", "http://www.stack.nl/~geertj/");
    aboutData.addAuthor("Pietro Iglio", I18N_NOOP("Original author"),
            "*****@*****.**");

    KCmdLineArgs::init(argc, argv, &aboutData);
    KCmdLineArgs::addCmdLineOptions(options);
    KApplication::disableAutoDcopRegistration();
    // kdesu doesn't process SM events, so don't even connect to ksmserver
    QCString session_manager = getenv( "SESSION_MANAGER" );
    unsetenv( "SESSION_MANAGER" );
    KApplication app;
    // but propagate it to the started app
    if (session_manager.data())
    {
        setenv( "SESSION_MANAGER", session_manager.data(), 1 );
    }
    
    {
        KStartupInfoId id;
        id.initId( kapp->startupId());
        id.setupStartupEnv(); // make DESKTOP_STARTUP_ID env. var. available again
    }

    int result = startApp();

    if (result == 127)
    {
        KMessageBox::sorry(0, i18n("Command '%1' not found.").arg(command));
    }

    return result;
}
bool PimUniqueApplication::start( KUniqueApplication::StartFlags flags )
{
  const QString appName = KCmdLineArgs::aboutData()->appName();
  // Try talking to /appName_PimApplication in org.kde.appName,
  // (which could be kontact or the standalone application),
  // otherwise fall back to standard KUniqueApplication behavior (start appName).

  const QString serviceName = "org.kde." + appName;
  if ( tryToInitDBusConnection().interface()->isServiceRegistered( serviceName ) ) {
    QByteArray saved_args;
    QDataStream ds( &saved_args, QIODevice::WriteOnly );
    KCmdLineArgs::saveAppArgs( ds );

    QByteArray new_asn_id;
#if defined Q_WS_X11
    KStartupInfoId id;
    if ( kapp ) { // KApplication constructor unsets the env. variable
      id.initId( kapp->startupId() );
    } else {
      id = KStartupInfo::currentStartupIdEnv();
    }
    if ( !id.none() ) {
      new_asn_id = id.id();
    }
#endif

    KWindowSystem::allowExternalProcessWindowActivation();

    const QString objectName = QString( '/' ) + appName + "_PimApplication";
    //kDebug() << objectName;
    QDBusInterface iface(
      serviceName, objectName, "org.kde.KUniqueApplication", QDBusConnection::sessionBus() );
    QDBusReply<int> reply;
    if ( iface.isValid() &&
         ( reply = iface.call( "newInstance", new_asn_id, saved_args ) ).isValid() ) {
      return false; // success means that main() can exit now.
    }
  }

  QDBusConnection::disconnectFromBus( _k_sessionBusName );

  //kDebug() << "kontact not running -- start standalone application";
  // kontact not running -- start standalone application.
  return KUniqueApplication::start( flags );
}
示例#3
0
文件: main.cpp 项目: emmanuel099/kio
void KIOExec::slotRunApp()
{
    if ( fileList.isEmpty() ) {
        qDebug() << "No files downloaded -> exiting";
        mExited = true;
        QApplication::exit(1);
        return;
    }

    KService service(QStringLiteral("dummy"), command, QString());

    QList<QUrl> list;
    // Store modification times
    QList<FileInfo>::Iterator it = fileList.begin();
    for ( ; it != fileList.end() ; ++it )
    {
        QFileInfo info(QFile::encodeName(it->path));
        it->time = info.lastModified();
        QUrl url = QUrl::fromLocalFile(it->path);
        list << url;
    }

    KIO::DesktopExecParser execParser(service, list);
    QStringList params = execParser.resultingArguments();

    qDebug() << "EXEC " << params.join(QStringLiteral(" "));

#if (QT_VERSION >= QT_VERSION_CHECK(5, 4, 0))
    // propagate the startup identification to the started process
    KStartupInfoId id;
    QByteArray startupId;
#if HAVE_X11
    if (QX11Info::isPlatformX11()) {
        startupId = QX11Info::nextStartupId();
    }
#endif
    id.initId(startupId);
    id.setupStartupEnv();
#endif

    QString exe( params.takeFirst() );
    const int exit_code = QProcess::execute( exe, params );

#if (QT_VERSION >= QT_VERSION_CHECK(5, 4, 0))
    KStartupInfo::resetStartupEnv();
#endif

    qDebug() << "EXEC done";

    // Test whether one of the files changed
    for(it = fileList.begin(); it != fileList.end(); ++it )
    {
        QString src = it->path;
        const QUrl dest = it->url;
        QFileInfo info(src);
        if ( info.exists() && (it->time != info.lastModified()) )
        {
            if ( mTempFiles )
            {
                if ( KMessageBox::questionYesNo( 0L,
                                                 i18n( "The supposedly temporary file\n%1\nhas been modified.\nDo you still want to delete it?", dest.toDisplayString(QUrl::PreferLocalFile)),
                                                 i18n( "File Changed" ), KStandardGuiItem::del(), KGuiItem(i18n("Do Not Delete")) ) != KMessageBox::Yes )
                    continue; // don't delete the temp file
            }
            else if ( ! dest.isLocalFile() )  // no upload when it's already a local file
            {
                if ( KMessageBox::questionYesNo( 0L,
                                                 i18n( "The file\n%1\nhas been modified.\nDo you want to upload the changes?" , dest.toDisplayString()),
                                                 i18n( "File Changed" ), KGuiItem(i18n("Upload")), KGuiItem(i18n("Do Not Upload")) ) == KMessageBox::Yes )
                {
                    qDebug() << "src='" << src << "'  dest='" << dest << "'";
                    // Do it the synchronous way.
                    KIO::CopyJob* job = KIO::copy(QUrl::fromLocalFile(src), dest);
                    if ( !job->exec() )
                    {
                        KMessageBox::error( 0L, job->errorText() );
                        continue; // don't delete the temp file
                    }
                }
            }
        }

        if ((!dest.isLocalFile() || mTempFiles) && exit_code == 0) {
            // Wait for a reasonable time so that even if the application forks on startup (like OOo or amarok)
            // it will have time to start up and read the file before it gets deleted. #130709.
            qDebug() << "sleeping...";
            QThread::currentThread()->sleep(180); // 3 mn
            qDebug() << "about to delete " << src;
            QFile( QFile::encodeName(src) ).remove();
        }
    }

    mExited = true;
    QApplication::exit(exit_code);
}
示例#4
0
static int startApp()
{
    KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
    // Stop daemon and exit?
    if (args->isSet("s"))
    {
        KDEsuClient client;
        if (client.ping() == -1)
        {
            kdError(1206) << "Daemon not running -- nothing to stop\n";
            exit(1);
        }
        if (client.stopServer() != -1)
        {
            kdDebug(1206) << "Daemon stopped\n";
            exit(0);
        }
        kdError(1206) << "Could not stop daemon\n";
        exit(1);
    }

    QString icon;
    if ( args->isSet("i"))
	icon = args->getOption("i");	

    bool prompt = true;
    if ( args->isSet("d"))
	prompt = false;

    // Get target uid
    QCString user = args->getOption("u");
    QCString auth_user = user;
    struct passwd *pw = getpwnam(user);
    if (pw == 0L)
    {
        kdError(1206) << "User " << user << " does not exist\n";
        exit(1);
    }
    bool change_uid = (getuid() != pw->pw_uid);

    // If file is writeable, do not change uid
    QString file = QFile::decodeName(args->getOption("f"));
    if (change_uid && !file.isEmpty())
    {
        if (file.at(0) != '/')
        {
            KStandardDirs dirs;
            dirs.addKDEDefaults();
            file = dirs.findResource("config", file);
            if (file.isEmpty())
            {
                kdError(1206) << "Config file not found: " << file << "\n";
                exit(1);
            }
        }
        QFileInfo fi(file);
        if (!fi.exists())
        {
            kdError(1206) << "File does not exist: " << file << "\n";
            exit(1);
        }
        change_uid = !fi.isWritable();
    }

    // Get priority/scheduler
    QCString tmp = args->getOption("p");
    bool ok;
    int priority = tmp.toInt(&ok);
    if (!ok || (priority < 0) || (priority > 100))
    {
        KCmdLineArgs::usage(i18n("Illegal priority: %1").arg(tmp));
        exit(1);
    }
    int scheduler = SuProcess::SchedNormal;
    if (args->isSet("r"))
        scheduler = SuProcess::SchedRealtime;
    if ((priority > 50) || (scheduler != SuProcess::SchedNormal))
    {
        change_uid = true;
        auth_user = "******";
    }

    // Get command
    if (args->isSet("c"))
    {
        command = args->getOption("c");
        for (int i=0; i<args->count(); i++)
        {
            QString arg = QFile::decodeName(args->arg(i));
            KRun::shellQuote(arg);
            command += " ";
            command += QFile::encodeName(arg);
        }
    }
    else 
    {
        if( args->count() == 0 )
        {
            KCmdLineArgs::usage(i18n("No command specified."));
            exit(1);
        }
        command = args->arg(0);
        for (int i=1; i<args->count(); i++)
        {
            QString arg = QFile::decodeName(args->arg(i));
            KRun::shellQuote(arg);
            command += " ";
            command += QFile::encodeName(arg);
        }
    }

    // Don't change uid if we're don't need to.
    if (!change_uid)
    {
        int result = system(command);
        result = WEXITSTATUS(result);
        return result;
    }

    // Check for daemon and start if necessary
    bool just_started = false;
    bool have_daemon = true;
    KDEsuClient client;
    if (!client.isServerSGID())
    {
        kdWarning(1206) << "Daemon not safe (not sgid), not using it.\n";
        have_daemon = false;
    }
    else if (client.ping() == -1)
    {
        if (client.startServer() == -1)
        {
            kdWarning(1206) << "Could not start daemon, reduced functionality.\n";
            have_daemon = false;
        }
        just_started = true;
    }

    // Try to exec the command with kdesud.
    bool keep = !args->isSet("n") && have_daemon;
    bool terminal = args->isSet("t");
    bool new_dcop = args->isSet("newdcop");
    bool withIgnoreButton = args->isSet("ignorebutton");
    
    QCStringList env;
    QCString options;
    env << ( "DESKTOP_STARTUP_ID=" + kapp->startupId());
    
    if (pw->pw_uid)
    {
       // Only propagate KDEHOME for non-root users,
       // root uses KDEROOTHOME
       
       // Translate the KDEHOME of this user to the new user.
       QString kdeHome = KGlobal::dirs()->relativeLocation("home", KGlobal::dirs()->localkdedir());
       if (kdeHome[0] != '/')
          kdeHome.prepend("~/"); 
       else
          kdeHome=QString::null; // Use default

       env << ("KDEHOME="+ QFile::encodeName(kdeHome));
    }

    KUser u;
    env << (QCString) ("KDESU_USER="******"KDESYCOCA="+QFile::encodeName(locateLocal("cache", "ksycoca"));
        env << ksycoca;

        options += "xf"; // X-only, dcop forwarding enabled.
    }

    if (keep && !terminal && !just_started)
    {
        client.setPriority(priority);
        client.setScheduler(scheduler);
        int result = client.exec(command, user, options, env);
        if (result == 0)
        {
           result = client.exitCode();
           return result;
        }
    }

    // Set core dump size to 0 because we will have
    // root's password in memory.
    struct rlimit rlim;
    rlim.rlim_cur = rlim.rlim_max = 0;
    if (setrlimit(RLIMIT_CORE, &rlim))
    {
        kdError(1206) << "rlimit(): " << ERR << "\n";
        exit(1);
    }

    // Read configuration
    KConfig *config = KGlobal::config();
    config->setGroup("Passwords");
    int timeout = config->readNumEntry("Timeout", defTimeout);

    // Check if we need a password
    SuProcess proc;
    proc.setUser(auth_user);
    int needpw = proc.checkNeedPassword();
    if (needpw < 0)
    {
        QString err = i18n("Su returned with an error.\n");
        KMessageBox::error(0L, err);
        exit(1);
    }
    if (needpw == 0)
    {
        keep = 0;
        kdDebug() << "Don't need password!!\n";
    }

    // Start the dialog
    QCString password;
    if (needpw)
    {
        KStartupInfoId id;
        id.initId( kapp->startupId());
        KStartupInfoData data;
        data.setSilent( KStartupInfoData::Yes );
        KStartupInfo::sendChange( id, data );
        KDEsuDialog dlg(user, auth_user, keep && !terminal,icon, withIgnoreButton);
	if (prompt)
	    dlg.addLine(i18n("Command:"), command);
        if ((priority != 50) || (scheduler != SuProcess::SchedNormal))
        {
            QString prio;
            if (scheduler == SuProcess::SchedRealtime)
                prio += i18n("realtime: ");
            prio += QString("%1/100").arg(priority);
	    if (prompt)
		dlg.addLine(i18n("Priority:"), prio);
        }
        int ret = dlg.exec();
        if (ret == KDEsuDialog::Rejected)
        {
            KStartupInfo::sendFinish( id );
            exit(0);
        }
        if (ret == KDEsuDialog::AsUser)
            change_uid = false;
        password = dlg.password();
        keep = dlg.keep();
        data.setSilent( KStartupInfoData::No );
        KStartupInfo::sendChange( id, data );
    }

    // Some events may need to be handled (like a button animation)
    kapp->processEvents();

    // Run command
    if (!change_uid)
    {
        int result = system(command);
        result = WEXITSTATUS(result);
        return result;
    }
    else if (keep && have_daemon)
    {
        client.setPass(password, timeout);
        client.setPriority(priority);
        client.setScheduler(scheduler);
        int result = client.exec(command, user, options, env);
        if (result == 0)
        {
            result = client.exitCode();
            return result;
        }
    } else
    {
        SuProcess proc;
        proc.setTerminal(terminal);
        proc.setErase(true);
        proc.setUser(user);
        if (!new_dcop)
        {
            proc.setXOnly(true);
            proc.setDCOPForwarding(true);
        }
        proc.setEnvironment(env);
        proc.setPriority(priority);
        proc.setScheduler(scheduler);
        proc.setCommand(command);
        int result = proc.exec(password);
        return result;
    }
    return -1;
}
示例#5
0
void KrashConfig :: readConfig()
{
  KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
  m_signalnum = args->getOption( "signal" ).toInt();
  m_pid = args->getOption( "pid" ).toInt();
  m_startedByKdeinit = args->isSet("kdeinit");
  m_safeMode = args->isSet("safer");
  m_execname = args->getOption( "appname" );
  if ( !args->getOption( "apppath" ).isEmpty() )
    m_execname.prepend( args->getOption( "apppath" ) + '/' );

  QCString programname = args->getOption("programname");
  if (programname.isEmpty())
    programname.setStr(I18N_NOOP("unknown"));
  // leak some memory... Well. It's only done once anyway :-)
  const char * progname = qstrdup(programname);
  m_aboutData = new KAboutData(args->getOption("appname"),
                               progname,
                               args->getOption("appversion"),
                               0, 0, 0, 0, 0,
                               args->getOption("bugaddress"));

  QCString startup_id( args->getOption( "startupid" ));
  if (!startup_id.isEmpty())
  { // stop startup notification
    KStartupInfoId id;
    id.initId( startup_id );
    KStartupInfo::sendFinish( id );
  }

  KConfig *config = KGlobal::config();
  config->setGroup("drkonqi");

  // maybe we should check if it's relative?
  QString configname = config->readEntry("ConfigName",
                                         QString::fromLatin1("enduser"));

  QString debuggername = config->readEntry("Debugger",
                                           QString::fromLatin1("gdb"));

  KConfig debuggers(QString::fromLatin1("debuggers/%1rc").arg(debuggername),
                    true, false, "appdata");

  debuggers.setGroup("General");
  m_debugger = debuggers.readPathEntry("Exec");
  m_debuggerBatch = debuggers.readPathEntry("ExecBatch");
  m_tryExec = debuggers.readPathEntry("TryExec");
  m_backtraceCommand = debuggers.readEntry("BacktraceCommand");
  m_removeFromBacktraceRegExp = debuggers.readEntry("RemoveFromBacktraceRegExp");
  m_invalidStackFrameRegExp = debuggers.readEntry("InvalidStackFrameRegExp");
  m_frameRegExp = debuggers.readEntry("FrameRegExp");
  m_neededInValidBacktraceRegExp = debuggers.readEntry("NeededInValidBacktraceRegExp");
  m_kcrashRegExp = debuggers.readEntry("KCrashRegExp");

  KConfig preset(QString::fromLatin1("presets/%1rc").arg(configname),
                 true, false, "appdata");

  preset.setGroup("ErrorDescription");
  if (preset.readBoolEntry("Enable"), true)
    m_errorDescriptionText = preset.readEntry("Name");

  preset.setGroup("WhatToDoHint");
  if (preset.readBoolEntry("Enable"))
    m_whatToDoText = preset.readEntry("Name");

  preset.setGroup("General");
  m_showbugreport = preset.readBoolEntry("ShowBugReportButton", false);
  m_showdebugger = m_showbacktrace = m_pid != 0;
  if (m_showbacktrace)
  {
    m_showbacktrace = preset.readBoolEntry("ShowBacktraceButton", true);
    m_showdebugger = preset.readBoolEntry("ShowDebugButton", true);
  }
  m_disablechecks = preset.readBoolEntry("DisableChecks", false);

  bool b = preset.readBoolEntry("SignalDetails", true);

  QString str = QString::number(m_signalnum);
  // use group unknown if signal not found
  if (!preset.hasGroup(str))
    str = QString::fromLatin1("unknown");
  preset.setGroup(str);
  m_signalName = preset.readEntry("Name");
  if (b)
    m_signalText = preset.readEntry("Comment");
}
示例#6
0
文件: kdesu.cpp 项目: KDE/kde-runtime
int main(int argc, char *argv[])
{
    // FIXME: this can be considered a poor man's solution, as it's not
    // directly obvious to a gui user. :)
    // anyway, i vote against removing it even when we have a proper gui
    // implementation.  -- ossi

    QByteArray duser = qgetenv("ADMIN_ACCOUNT");
    if (duser.isEmpty())
        duser = "******";

    KAboutData aboutData("kdesu", 0, ki18n("KDE su"),
            Version, ki18n("Runs a program with elevated privileges."),
            KAboutData::License_Artistic,
            ki18n("Copyright (c) 1998-2000 Geert Jansen, Pietro Iglio"));
    aboutData.addAuthor(ki18n("Geert Jansen"), ki18n("Maintainer"),
            "*****@*****.**", "http://www.stack.nl/~geertj/");
    aboutData.addAuthor(ki18n("Pietro Iglio"), ki18n("Original author"),
            "*****@*****.**");
    aboutData.setProgramIconName("dialog-password");

    KCmdLineArgs::init(argc, argv, &aboutData);

    // NOTE: if you change the position of the -u switch, be sure to adjust it
    // at the beginning of main()
    KCmdLineOptions options;
    options.add("!+command", ki18n("Specifies the command to run as separate arguments"));
    options.add("c <command>", ki18n("Specifies the command to run as one string"));
    options.add("f <file>", ki18n("Run command under target uid if <file> is not writable"));
    options.add("u <user>", ki18n("Specifies the target uid"), duser);
    options.add("n", ki18n("Do not keep password"));
    options.add("s", ki18n("Stop the daemon (forgets all passwords)"));
    options.add("t", ki18n("Enable terminal output (no password keeping)"));
    options.add("p <prio>", ki18n("Set priority value: 0 <= prio <= 100, 0 is lowest"), "50");
    options.add("r", ki18n("Use realtime scheduling"));
    options.add("noignorebutton", ki18n("Do not display ignore button"));
    options.add("i <icon name>", ki18n("Specify icon to use in the password dialog"));
    options.add("d", ki18n("Do not show the command to be run in the dialog"));
#ifdef Q_WS_X11
    /* KDialog originally used --embed for attaching the dialog box.  However this is misleading and so we changed to --attach.
     * For consistancy, we silently map --embed to --attach */
    options.add("attach <winid>", ki18nc("Transient means that the kdesu app will be attached to the app specified by the winid so that it is like a dialog box rather than some separate program", "Makes the dialog transient for an X app specified by winid"));
    options.add("embed <winid>");
#endif
    KCmdLineArgs::addCmdLineOptions(options);

    //KApplication::disableAutoDcopRegistration();
    // kdesu doesn't process SM events, so don't even connect to ksmserver
    QByteArray session_manager = qgetenv( "SESSION_MANAGER" );
    if (!session_manager.isEmpty())
        unsetenv( "SESSION_MANAGER" );
    KApplication app;
    // but propagate it to the started app
    if (!session_manager.isEmpty())
        setenv( "SESSION_MANAGER", session_manager.data(), 1 );

    {
#ifdef Q_WS_X11
        KStartupInfoId id;
        id.initId( kapp->startupId());
        id.setupStartupEnv(); // make DESKTOP_STARTUP_ID env. var. available again
#endif
    }

    int result = startApp();

    if (result == 127)
    {
        KMessageBox::sorry(0, i18n("Cannot execute command '%1'.", QString::fromLocal8Bit(command)));
    }

    return result;
}
示例#7
0
文件: kdesu.cpp 项目: KDE/kde-runtime
static int startApp()
{
    KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
    // Stop daemon and exit?
    if (args->isSet("s"))
    {
        KDEsuClient client;
        if (client.ping() == -1)
        {
            kError(1206) << "Daemon not running -- nothing to stop\n";
            exit(1);
        }
        if (client.stopServer() != -1)
        {
            kDebug(1206) << "Daemon stopped\n";
            exit(0);
        }
        kError(1206) << "Could not stop daemon\n";
        exit(1);
    }

    QString icon;
    if ( args->isSet("i"))
	icon = args->getOption("i");

    bool prompt = true;
    if ( args->isSet("d"))
	prompt = false;

    // Get target uid
    QByteArray user = args->getOption("u").toLocal8Bit();
    QByteArray auth_user = user;
    struct passwd *pw = getpwnam(user);
    if (pw == 0L)
    {
        kError(1206) << "User " << user << " does not exist\n";
        exit(1);
    }
    bool other_uid = (getuid() != pw->pw_uid);
    bool change_uid = other_uid;
    if (!change_uid) {
        char *cur_user = getenv("USER");
        if (!cur_user)
            cur_user = getenv("LOGNAME");
        change_uid = (!cur_user || user != cur_user);
    }

    // If file is writeable, do not change uid
    QString file = args->getOption("f");
    if (other_uid && !file.isEmpty())
    {
        if (file.at(0) != '/')
        {
            KStandardDirs dirs;
            file = dirs.findResource("config", file);
            if (file.isEmpty())
            {
                kError(1206) << "Config file not found: " << file << "\n";
                exit(1);
            }
        }
        QFileInfo fi(file);
        if (!fi.exists())
        {
            kError(1206) << "File does not exist: " << file << "\n";
            exit(1);
        }
        change_uid = !fi.isWritable();
    }

    // Get priority/scheduler
    QString tmp = args->getOption("p");
    bool ok;
    int priority = tmp.toInt(&ok);
    if (!ok || (priority < 0) || (priority > 100))
    {
        KCmdLineArgs::usageError(i18n("Illegal priority: %1", tmp));
        exit(1);
    }
    int scheduler = SuProcess::SchedNormal;
    if (args->isSet("r"))
        scheduler = SuProcess::SchedRealtime;
    if ((priority > 50) || (scheduler != SuProcess::SchedNormal))
    {
        change_uid = true;
        auth_user = "******";
    }

    // Get command
    if (args->isSet("c"))
    {
        command = args->getOption("c").toLocal8Bit();
        // Accepting additional arguments here is somewhat weird,
        // but one can conceive use cases: have a complex command with
        // redirections and additional file names which need to be quoted
        // safely.
    }
    else
    {
        if( args->count() == 0 )
        {
            KCmdLineArgs::usageError(i18n("No command specified."));
            exit(1);
        }
    }
    for (int i = 0; i < args->count(); i++)
    {
        command += ' ';
        command += QFile::encodeName(KShell::quoteArg(args->arg(i)));
    }

    // Don't change uid if we're don't need to.
    if (!change_uid)
    {
        int result = system(command);
        result = WEXITSTATUS(result);
        return result;
    }

    // Check for daemon and start if necessary
    bool just_started = false;
    bool have_daemon = true;
    KDEsuClient client;
    if (!client.isServerSGID())
    {
        kWarning(1206) << "Daemon not safe (not sgid), not using it.\n";
        have_daemon = false;
    }
    else if (client.ping() == -1)
    {
        if (client.startServer() == -1)
        {
            kWarning(1206) << "Could not start daemon, reduced functionality.\n";
            have_daemon = false;
        }
        just_started = true;
    }

    // Try to exec the command with kdesud.
    bool keep = !args->isSet("n") && have_daemon;
    bool terminal = args->isSet("t");
    bool withIgnoreButton = args->isSet("ignorebutton");
    int winid = -1;
    bool attach = args->isSet("attach");
    if(attach) {
        winid = args->getOption("attach").toInt(&attach, 0);  //C style parsing.  If the string begins with "0x", base 16 is used; if the string begins with "0", base 8 is used; otherwise, base 10 is used.
        if(!attach)
            kWarning(1206) << "Specified winid to attach to is not a valid number";
    } else if(args->isSet("embed")) {
        /* KDialog originally used --embed for attaching the dialog box.  However this is misleading and so we changed to --attach.
         * For consistancy, we silently map --embed to --attach */
        attach = true;
        winid = args->getOption("embed").toInt(&attach, 0);  //C style parsing.  If the string begins with "0x", base 16 is used; if the string begins with "0", base 8 is used; otherwise, base 10 is used.
        if(!attach)
            kWarning(1206) << "Specified winid to attach to is not a valid number";
    }


    QList<QByteArray> env;
    QByteArray options;
    env << ( "DESKTOP_STARTUP_ID=" + kapp->startupId());

    if (pw->pw_uid)
    {
       // Only propagate KDEHOME for non-root users,
       // root uses KDEROOTHOME

       // Translate the KDEHOME of this user to the new user.
       QString kdeHome = KGlobal::dirs()->relativeLocation("home", KGlobal::dirs()->localkdedir());
       if (kdeHome[0] != '/')
          kdeHome.prepend("~/");
       else
          kdeHome.clear(); // Use default

       env << ("KDEHOME="+ QFile::encodeName(kdeHome));
    }

    KUser u;
    env << (QByteArray) ("KDESU_USER="******"rlimit(): " << ERR << "\n";
        exit(1);
    }

    // Read configuration
    KConfigGroup config(KGlobal::config(), "Passwords");
    int timeout = config.readEntry("Timeout", defTimeout);

    // Check if we need a password
    SuProcess proc;
    proc.setUser(auth_user);
    int needpw = proc.checkNeedPassword();
    if (needpw < 0)
    {
        QString err = i18n("Su returned with an error.\n");
        KMessageBox::error(0L, err);
        exit(1);
    }
    if (needpw == 0)
    {
        keep = 0;
        kDebug() << "Don't need password!!\n";
    }

    // Start the dialog
    QString password;
    if (needpw)
    {
#ifdef Q_WS_X11
        KStartupInfoId id;
        id.initId( kapp->startupId());
        KStartupInfoData data;
        data.setSilent( KStartupInfoData::Yes );
        KStartupInfo::sendChange( id, data );
#endif
        KDEsuDialog dlg(user, auth_user, keep && !terminal, icon, withIgnoreButton);
        if (prompt)
            dlg.addCommentLine(i18n("Command:"), QFile::decodeName(command));
        if (defKeep)
            dlg.setKeepPassword(true);

        if ((priority != 50) || (scheduler != SuProcess::SchedNormal))
        {
            QString prio;
            if (scheduler == SuProcess::SchedRealtime)
                prio += i18n("realtime: ");
            prio += QString("%1/100").arg(priority);
            if (prompt)
                dlg.addCommentLine(i18n("Priority:"), prio);
        }

	//Attach dialog
#ifdef Q_WS_X11
	if(attach)
            KWindowSystem::setMainWindow(&dlg, (WId)winid);
#endif
        int ret = dlg.exec();
        if (ret == KDEsuDialog::Rejected)
        {
#ifdef Q_WS_X11
            KStartupInfo::sendFinish( id );
#endif
            exit(1);
        }
        if (ret == KDEsuDialog::AsUser)
            change_uid = false;
        password = dlg.password();
        keep = dlg.keepPassword();
#ifdef Q_WS_X11
        data.setSilent( KStartupInfoData::No );
        KStartupInfo::sendChange( id, data );
#endif
    }

    // Some events may need to be handled (like a button animation)
    kapp->processEvents();

    // Run command
    if (!change_uid)
    {
        int result = system(command);
        result = WEXITSTATUS(result);
        return result;
    }
    else if (keep && have_daemon)
    {
        client.setPass(password.toLocal8Bit(), timeout);
        client.setPriority(priority);
        client.setScheduler(scheduler);
        int result = client.exec(command, user, options, env);
        if (result == 0)
        {
            result = client.exitCode();
            return result;
        }
    } else
    {
        SuProcess proc;
        proc.setTerminal(terminal);
        proc.setErase(true);
        proc.setUser(user);
        proc.setEnvironment(env);
        proc.setPriority(priority);
        proc.setScheduler(scheduler);
        proc.setCommand(command);
        int result = proc.exec(password.toLocal8Bit());
        return result;
    }
    return -1;
}