Salome HOME
[EDF30235] : Update of PBS parametrization
[tools/libbatch.git] / src / Core / CommunicationProtocolRSH.cxx
1 // Copyright (C) 2007-2021  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 /*
23  *  CommunicationProtocolRSH.cxx :
24  *
25  *  Created on: 14 sept. 2009
26  *  Author : Renaud BARATE - EDF R&D
27  */
28
29 #ifdef WIN32
30 #include <direct.h>
31 #include <iostream>
32
33 #include <RunTimeException.hxx>
34 #endif
35
36 #include <libbatch_config.h>
37
38 #include "CommunicationProtocolRSH.hxx"
39 #include "CommandsOverloader.hxx"
40 #include "Log.hxx"
41
42 using namespace std;
43
44 namespace Batch {
45
46   CommunicationProtocolRSH::CommunicationProtocolRSH()
47   : CommunicationProtocol(RSH)
48   {
49   }
50
51   vector<string> CommunicationProtocolRSH::getExecCommandArgs(const string & subCommand,
52                                                               const string & host,
53                                                               const string & user) const
54   {
55     vector<string> cmd;
56
57     cmd.push_back(CommandsOverloader::getInstance().RSH_Command());
58     cmd.push_back(host);
59
60     if (user.size() > 0) {
61       cmd.push_back("-l");
62       cmd.push_back(user);
63     }
64
65 #ifdef WIN32
66     cmd.push_back("-n");
67 #endif
68
69     cmd.push_back(subCommand);
70
71     return cmd;
72   }
73
74   vector<string> CommunicationProtocolRSH::getCopyCommandArgs(const string & sourcePath,
75                                                               const string & sourceHost,
76                                                               const string & sourceUser,
77                                                               const string & destinationPath,
78                                                               const string & destinationHost,
79                                                               const string & destinationUser) const
80   {
81     vector<string> cmd;
82
83     string fullSource;
84     if (sourceHost.size() != 0) {
85       if (sourceUser.size() != 0) {
86 #ifdef WIN32
87         fullSource += sourceHost + "." + sourceUser + ":";
88 #else
89         fullSource += sourceUser + "@" + sourceHost + ":";
90 #endif
91       } else {
92         fullSource += sourceHost + ":";
93       }
94     }
95     fullSource += sourcePath;
96
97     string fullDestination;
98     if (destinationHost.size() != 0) {
99       if (destinationUser.size() != 0) {
100 #ifdef WIN32
101         fullDestination += destinationHost + "." + destinationUser + ":";
102 #else
103         fullDestination += destinationUser + "@" + destinationHost + ":";
104 #endif
105       } else {
106         fullDestination += destinationHost + ":";
107       }
108     }
109     fullDestination += destinationPath;
110
111     cmd.push_back(CommandsOverloader::getInstance().RCP_Command());
112     cmd.push_back("-r");
113     cmd.push_back(fullSource);
114     cmd.push_back(fullDestination);
115
116     return cmd;
117   }
118
119 #ifdef WIN32
120   int CommunicationProtocolRSH::copyFile(const std::string & sourcePath,
121                                          const std::string & sourceHost,
122                                          const std::string & sourceUser,
123                                          const std::string & destinationPath,
124                                          const std::string & destinationHost,
125                                          const std::string & destinationUser) const
126   {
127     // On Windows, we can't use drive letters in the paths of rcp command because they
128     // are confused with host names. So we must first change the working directory and
129     // then copy the file using its path without the drive letter.
130
131     // Extract the drive letter from the source path
132     string sourcePathWithoutDrive;
133     char sourceDriveLetter = getDriveLetter(sourcePath, &sourcePathWithoutDrive);
134     // Error if we have a drive letter and it is a remote path
135     if (sourceDriveLetter != '\0' && sourceHost.size() != 0)
136       throw RunTimeException(string("Invalid path: ") + sourcePath + " for host " + sourceHost);
137
138     // Extract the drive letter from the destination path
139     string destinationPathWithoutDrive;
140     char destinationDriveLetter = getDriveLetter(destinationPath, &destinationPathWithoutDrive);
141     // Error if we have a drive letter and it is a remote path
142     if (destinationDriveLetter != '\0' && destinationHost.size() != 0)
143       throw RunTimeException(string("Invalid path: ") + destinationPath + " for host " + destinationHost);
144
145     // Error if we have two drive letters and they are different
146     if (sourceDriveLetter != '\0' && destinationDriveLetter != '\0' &&
147         sourceDriveLetter != destinationDriveLetter)
148       throw RunTimeException(string("Can't use RCP to copy files between different drives: ") +
149                              sourcePath + (", ") + destinationPath);
150
151     // Now get the drive letter to use if there is one
152     char driveLetter = (sourceDriveLetter != '\0') ? sourceDriveLetter : destinationDriveLetter;
153
154     // Get the drive of the current working directory
155     char cwd[_MAX_PATH];
156     _getcwd(cwd, _MAX_PATH);
157     char currentDrive = getDriveLetter(cwd);
158
159     // Change working directory if necessary
160     if (driveLetter != '\0' && driveLetter != currentDrive) {
161       char newdir[3];
162       newdir[0] = driveLetter;
163       newdir[1] = ':';
164       newdir[2] = '\0';
165       LOG("Changing directory: " << newdir);
166       _chdir(newdir);
167     }
168
169     int status = CommunicationProtocol::copyFile(sourcePathWithoutDrive, sourceHost, sourceUser,
170                                                  destinationPathWithoutDrive, destinationHost, destinationUser);
171
172     // Go back to previous directory if necessary
173     if (driveLetter != '\0' && driveLetter != currentDrive) {
174       LOG("Changing directory: " << cwd);
175       _chdir(cwd);
176     }
177
178     return status;
179   }
180
181   char CommunicationProtocolRSH::getDriveLetter(const string & path, string * pathWithoutDrive) const
182   {
183     if (path.find(':') != string::npos) {
184       // Error if the colon is not the second character
185       if (path.size() < 2 || path[1] != ':')
186         throw RunTimeException(string("Invalid path: ") + path);
187       else {
188         if (pathWithoutDrive != NULL) *pathWithoutDrive = path.substr(2);
189         return path[0];
190       }
191     } else {
192       if (pathWithoutDrive != NULL) *pathWithoutDrive = path;
193       return '\0';
194     }
195   }
196
197 #endif
198
199 }