From 8ce8ab45edc6bf59e9caee15a66707ec17fbe6ca Mon Sep 17 00:00:00 2001 From: micio Date: Thu, 20 Jan 2011 19:32:03 +0000 Subject: [PATCH] Bazaar/SysExec : completed superuser functions with Xauth git-svn-id: svn://ultimatepp.org/upp/trunk@3049 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- bazaar/SysExec/SudoLib.cpp | 72 +++++++++++++++++++++++++++++--------- 1 file changed, 55 insertions(+), 17 deletions(-) diff --git a/bazaar/SysExec/SudoLib.cpp b/bazaar/SysExec/SudoLib.cpp index b5c39ffe1..3e46a291d 100644 --- a/bazaar/SysExec/SudoLib.cpp +++ b/bazaar/SysExec/SudoLib.cpp @@ -41,6 +41,22 @@ bool SudoExec(String user, String const &password, String const &args, VectorMap VectorMapenv(envir, 1); if(env.Find("DBUS_SESSION_BUS_ADDRESS")) env.RemoveKey("DBUS_SESSION_BUS_ADDRESS"); + + // setup XAUTHORITY for new user, if different + // from current one -- this will allow using X display + // for spawned user + if(user != GetUserName()) + { + String xFile = env.Get("XAUTHORITY", "/home/" + GetUserName() + "/.Xauthority"); + if(FileExists(xFile)) + { + // create a temp location for copied xFile + String tmpFile = GetTempFileName(); + FileCopy(xFile, tmpFile); + env.RemoveKey("XAUTHORITY"); + env.Add("XAUTHORITY", tmpFile); + } + } // prepare args for sudo execution String sudoArgs = "-S -E -E -p gimmipass "; @@ -103,16 +119,25 @@ bool SudoExec(String user, String const &password, String const &args, VectorMap } else { - // give sudo some time to get the password and launch the command - // (only if we shall not wait its completion...) - if(!wait) - Sleep(1000); - - // if we shall wait for sudo to complete its command - // we must wait for xpid process to terminate before leaving - // otherwise we just leave now int xstatus = 0; - if(wait) + + // if we shall NOT wait for sudo completion + // we must return asap, but AFTER disconnecting the pseudotty + if(!wait) + { + // give sudo some time to get the password and launch the command + // (only if we shall not wait its completion...) + Sleep(1000); + + // then disconnect it from pseudotty only if we're NOT + // waiting for process completion, otherwise this will + // make the last waitpid() return an error status + ioctl(pid, TIOCNOTTY); + } + + // otherwise, if we shall wait for sudo to complete its command + // we must wait for xpid process to terminate before leaving + else { while(!waitpid(xpid, &xstatus, WNOHANG)) Sleep(1000); @@ -121,11 +146,6 @@ bool SudoExec(String user, String const &password, String const &args, VectorMap else xstatus = -1; } - // then disconnect it from pseudotty only if we're NOT - // waiting for process completion, otherwise this will - // make the last waitpid() return an error status - if(!wait) - ioctl(pid, TIOCNOTTY); _exit(xstatus); } @@ -137,6 +157,7 @@ bool SudoExec(String user, String const &password, String const &args, VectorMap // associates an stream to child process pseudoterminal FILE *sudoFile = fdopen(masterPty, "w+"); +/* // notice that echo is off (it it is....) struct termios tio; tcgetattr (masterPty, &tio); @@ -145,6 +166,7 @@ bool SudoExec(String user, String const &password, String const &args, VectorMap usleep (1000); tcgetattr (masterPty, &tio); } +*/ // set input pipe to non-blocking, so we can read as we like // without hanging the program -- we need to check for 'password' input @@ -197,9 +219,23 @@ bool SudoExec(String user, String const &password, String const &args, VectorMap Sleep(100); _PutLine(sudoFile, ~password); + // hmmmm... it hangs sometimes here reading the status + // it seems that sudo sometimes ask for password AND don't put + // status back to terminal, OR something very wrong happens + // on forks above. As is better to not have a status than + // have the app hanging, we set a timeout on status read +/* // blocking stream again, to be sure to get the status back // (we know that must come 2 lines of status...) fcntl(masterPty, F_SETFL, fcntl(masterPty, F_GETFL) & ~O_NONBLOCK); +*/ + fd_set rfds; + struct timeval tv; + FD_ZERO(&rfds); + FD_SET(masterPty, &rfds); + tv.tv_sec = 1; + tv.tv_usec = 0; + select(masterPty + 1, &rfds, NULL, NULL, &tv); // skip the empty line after password _GetLine(sudoFile); @@ -246,8 +282,8 @@ bool SudoExec(String user, String const &password, String const &args, VectorMap bool res; // this one of we shall wait for command completion - if(wait) - { +// if(wait) +// { while(!waitpid( pid, &status, WNOHANG )) Sleep(1000); @@ -264,8 +300,9 @@ bool SudoExec(String user, String const &password, String const &args, VectorMap // close pseudoterminal fclose(sudoFile); - } +// } // and this one if we shall not wait +/* else { res = !line.StartsWith("sudo:"); @@ -291,6 +328,7 @@ bool SudoExec(String user, String const &password, String const &args, VectorMap _exit(0); } } +*/ return res; } }