X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/5abee4863220c2d9b135dc832b33c8680e5ba12e..8279242457d9be370f7a6f9337085d38506e967b:/methods/rsh.cc diff --git a/methods/rsh.cc b/methods/rsh.cc index d249ae961..7b8af6f9b 100644 --- a/methods/rsh.cc +++ b/methods/rsh.cc @@ -17,10 +17,12 @@ #include #include #include +#include +#include +#include #include #include -#include #include #include #include @@ -31,7 +33,6 @@ #include /*}}}*/ -const char *Prog; unsigned long TimeOut = 120; Configuration::Item const *RshOptions = 0; time_t RSHMethod::FailTime = 0; @@ -41,8 +42,10 @@ int RSHMethod::FailFd = -1; // RSHConn::RSHConn - Constructor /*{{{*/ // --------------------------------------------------------------------- /* */ -RSHConn::RSHConn(URI Srv) : Len(0), WriteFd(-1), ReadFd(-1), - ServerName(Srv), Process(-1) {} +RSHConn::RSHConn(std::string const &pProg, URI Srv) : Len(0), WriteFd(-1), ReadFd(-1), + ServerName(Srv), Prog(pProg), Process(-1) { + Buffer[0] = '\0'; +} /*}}}*/ // RSHConn::RSHConn - Destructor /*{{{*/ // --------------------------------------------------------------------- @@ -79,7 +82,7 @@ bool RSHConn::Open() if (Process != -1) return true; - if (Connect(ServerName.Host,ServerName.User) == false) + if (Connect(ServerName.Host,ServerName.Port,ServerName.User) == false) return false; return true; @@ -88,8 +91,15 @@ bool RSHConn::Open() // RSHConn::Connect - Fire up rsh and connect /*{{{*/ // --------------------------------------------------------------------- /* */ -bool RSHConn::Connect(std::string Host, std::string User) +bool RSHConn::Connect(std::string Host, unsigned int Port, std::string User) { + char *PortStr = NULL; + if (Port != 0) + { + if (asprintf (&PortStr, "%d", Port) == -1 || PortStr == NULL) + return _error->Errno("asprintf", _("Failed")); + } + // Create the pipes int Pipes[4] = {-1,-1,-1,-1}; if (pipe(Pipes) != 0 || pipe(Pipes+2) != 0) @@ -116,7 +126,7 @@ bool RSHConn::Connect(std::string Host, std::string User) // Probably should do // dup2(open("/dev/null",O_RDONLY),STDERR_FILENO); - Args[i++] = Prog; + Args[i++] = Prog.c_str(); // Insert user-supplied command line options Configuration::Item const *Opts = RshOptions; @@ -135,6 +145,10 @@ bool RSHConn::Connect(std::string Host, std::string User) Args[i++] = "-l"; Args[i++] = User.c_str(); } + if (PortStr != NULL) { + Args[i++] = "-p"; + Args[i++] = PortStr; + } if (Host.empty() == false) { Args[i++] = Host.c_str(); } @@ -144,6 +158,9 @@ bool RSHConn::Connect(std::string Host, std::string User) exit(100); } + if (PortStr != NULL) + free(PortStr); + ReadFd = Pipes[0]; WriteFd = Pipes[3]; SetNonBlock(Pipes[0],true); @@ -152,6 +169,10 @@ bool RSHConn::Connect(std::string Host, std::string User) close(Pipes[2]); return true; +} +bool RSHConn::Connect(std::string Host, std::string User) +{ + return Connect(Host, 0, User); } /*}}}*/ // RSHConn::ReadLine - Very simple buffered read with timeout /*{{{*/ @@ -213,15 +234,20 @@ bool RSHConn::WriteMsg(std::string &Text,bool Sync,const char *Fmt,...) va_list args; va_start(args,Fmt); - // sprintf the description - char S[512]; - vsnprintf(S,sizeof(S) - 4,Fmt,args); + // sprintf into a buffer + char Tmp[1024]; + vsnprintf(Tmp,sizeof(Tmp),Fmt,args); + va_end(args); + + // concat to create the real msg + std::string Msg; if (Sync == true) - strcat(S," 2> /dev/null || echo\n"); + Msg = std::string(Tmp) + " 2> /dev/null || echo\n"; else - strcat(S," 2> /dev/null\n"); + Msg = std::string(Tmp) + " 2> /dev/null\n"; // Send it off + const char *S = Msg.c_str(); unsigned long Len = strlen(S); unsigned long Start = 0; while (Len != 0) @@ -252,7 +278,7 @@ bool RSHConn::WriteMsg(std::string &Text,bool Sync,const char *Fmt,...) /*}}}*/ // RSHConn::Size - Return the size of the file /*{{{*/ // --------------------------------------------------------------------- -/* Right now for successfull transfer the file size must be known in +/* Right now for successful transfer the file size must be known in advance. */ bool RSHConn::Size(const char *Path,unsigned long long &Size) { @@ -357,29 +383,29 @@ bool RSHConn::Get(const char *Path,FileFd &To,unsigned long long Resume, /*}}}*/ // RSHMethod::RSHMethod - Constructor /*{{{*/ -// --------------------------------------------------------------------- -/* */ -RSHMethod::RSHMethod() : pkgAcqMethod("1.0",SendConfig) +RSHMethod::RSHMethod(std::string &&pProg) : aptMethod(std::move(pProg),"1.0",SendConfig) { signal(SIGTERM,SigTerm); signal(SIGINT,SigTerm); Server = 0; FailFd = -1; -}; +} /*}}}*/ // RSHMethod::Configuration - Handle a configuration message /*{{{*/ // --------------------------------------------------------------------- bool RSHMethod::Configuration(std::string Message) { - char ProgStr[100]; - - if (pkgAcqMethod::Configuration(Message) == false) + // enabling privilege dropping for this method requires configuration… + // … which is otherwise lifted straight from root, so use it by default. + _config->Set(std::string("Binary::") + Binary + "::APT::Sandbox::User", ""); + + if (aptMethod::Configuration(Message) == false) return false; - snprintf(ProgStr, sizeof ProgStr, "Acquire::%s::Timeout", Prog); - TimeOut = _config->FindI(ProgStr,TimeOut); - snprintf(ProgStr, sizeof ProgStr, "Acquire::%s::Options", Prog); - RshOptions = _config->Tree(ProgStr); + std::string const timeconf = std::string("Acquire::") + Binary + "::Timeout"; + TimeOut = _config->FindI(timeconf, TimeOut); + std::string const optsconf = std::string("Acquire::") + Binary + "::Options"; + RshOptions = _config->Tree(optsconf.c_str()); return true; } @@ -387,17 +413,18 @@ bool RSHMethod::Configuration(std::string Message) // RSHMethod::SigTerm - Clean up and timestamp the files on exit /*{{{*/ // --------------------------------------------------------------------- /* */ -void RSHMethod::SigTerm(int sig) +void RSHMethod::SigTerm(int) { if (FailFd == -1) _exit(100); - close(FailFd); - // Timestamp - struct utimbuf UBuf; - UBuf.actime = FailTime; - UBuf.modtime = FailTime; - utime(FailFile.c_str(),&UBuf); + // Transfer the modification times + struct timeval times[2]; + times[0].tv_sec = FailTime; + times[1].tv_sec = FailTime; + times[0].tv_usec = times[1].tv_usec = 0; + utimes(FailFile.c_str(), times); + close(FailFd); _exit(100); } @@ -416,7 +443,7 @@ bool RSHMethod::Fetch(FetchItem *Itm) // Connect to the server if (Server == 0 || Server->Comp(Get) == false) { delete Server; - Server = new RSHConn(Get); + Server = new RSHConn(Binary, Get); } // Could not connect is a transient error.. @@ -466,7 +493,7 @@ bool RSHMethod::Fetch(FetchItem *Itm) } // Open the file - Hashes Hash; + Hashes Hash(Itm->ExpectedHashes); { FileFd Fd(Itm->DestFile,FileFd::WriteAny); if (_error->PendingError() == true) @@ -475,7 +502,7 @@ bool RSHMethod::Fetch(FetchItem *Itm) URIStart(Res); FailFile = Itm->DestFile; - FailFile.c_str(); // Make sure we dont do a malloc in the signal handler + FailFile.c_str(); // Make sure we don't do a malloc in the signal handler FailFd = Fd.Fd(); bool Missing; @@ -484,10 +511,11 @@ bool RSHMethod::Fetch(FetchItem *Itm) Fd.Close(); // Timestamp - struct utimbuf UBuf; - UBuf.actime = FailTime; - UBuf.modtime = FailTime; - utime(FailFile.c_str(),&UBuf); + struct timeval times[2]; + times[0].tv_sec = FailTime; + times[1].tv_sec = FailTime; + times[0].tv_usec = times[1].tv_usec = 0; + utimes(FailFile.c_str(), times); // If the file is missing we hard fail otherwise transient fail if (Missing == true) @@ -497,30 +525,24 @@ bool RSHMethod::Fetch(FetchItem *Itm) } Res.Size = Fd.Size(); + struct timeval times[2]; + times[0].tv_sec = FailTime; + times[1].tv_sec = FailTime; + times[0].tv_usec = times[1].tv_usec = 0; + utimes(Fd.Name().c_str(), times); + FailFd = -1; } Res.LastModified = FailTime; Res.TakeHashes(Hash); - // Timestamp - struct utimbuf UBuf; - UBuf.actime = FailTime; - UBuf.modtime = FailTime; - utime(Queue->DestFile.c_str(),&UBuf); - FailFd = -1; - URIDone(Res); return true; } /*}}}*/ -int main(int argc, const char *argv[]) +int main(int, const char *argv[]) { - setlocale(LC_ALL, ""); - - RSHMethod Mth; - Prog = strrchr(argv[0],'/'); - Prog++; - return Mth.Run(); + return RSHMethod(flNotDir(argv[0])).Run(); }