Salome HOME
59caf2d28789cab4b565557ea7e4b6e4ebcc2e55
[tools/libbatch.git] / src / Core / CommunicationProtocolRSH.cxx
1 //  Copyright (C) 2007-2012  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.
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 <config.h>
37
38 #include "CommunicationProtocolRSH.hxx"
39
40 using namespace std;
41
42 namespace Batch {
43
44   CommunicationProtocolRSH::CommunicationProtocolRSH()
45   : CommunicationProtocol(RSH)
46   {
47   }
48
49   vector<string> CommunicationProtocolRSH::getExecCommandArgs(const string & subCommand,
50                                                               const string & host,
51                                                               const string & user) const
52   {
53     vector<string> cmd;
54
55     cmd.push_back(RSH_COMMAND);
56     cmd.push_back(host);
57
58     if (user.size() > 0) {
59       cmd.push_back("-l");
60       cmd.push_back(user);
61     }
62
63 #ifdef WIN32
64     cmd.push_back("-n");
65 #endif
66
67     cmd.push_back(subCommand);
68
69     return cmd;
70   }
71
72   vector<string> CommunicationProtocolRSH::getCopyCommandArgs(const string & sourcePath,
73                                                               const string & sourceHost,
74                                                               const string & sourceUser,
75                                                               const string & destinationPath,
76                                                               const string & destinationHost,
77                                                               const string & destinationUser) const
78   {
79     vector<string> cmd;
80
81     string fullSource;
82     if (sourceHost.size() != 0) {
83       if (sourceUser.size() != 0) {
84 #ifdef WIN32
85         fullSource += sourceHost + "." + sourceUser + ":";
86 #else
87         fullSource += sourceUser + "@" + sourceHost + ":";
88 #endif
89       } else {
90         fullSource += sourceHost + ":";
91       }
92     }
93     fullSource += sourcePath;
94
95     string fullDestination;
96     if (destinationHost.size() != 0) {
97       if (destinationUser.size() != 0) {
98 #ifdef WIN32
99         fullDestination += destinationHost + "." + destinationUser + ":";
100 #else
101         fullDestination += destinationUser + "@" + destinationHost + ":";
102 #endif
103       } else {
104         fullDestination += destinationHost + ":";
105       }
106     }
107     fullDestination += destinationPath;
108
109     cmd.push_back(RCP_COMMAND);
110     cmd.push_back("-r");
111     cmd.push_back(fullSource);
112     cmd.push_back(fullDestination);
113
114     return cmd;
115   }
116
117 #ifdef WIN32
118   int CommunicationProtocolRSH::copyFile(const std::string & sourcePath,
119                                          const std::string & sourceHost,
120                                          const std::string & sourceUser,
121                                          const std::string & destinationPath,
122                                          const std::string & destinationHost,
123                                          const std::string & destinationUser) const
124   {
125     // On Windows, we can't use drive letters in the paths of rcp command because they
126     // are confused with host names. So we must first change the working directory and
127     // then copy the file using its path without the drive letter.
128
129     // Extract the drive letter from the source path
130     string sourcePathWithoutDrive;
131     char sourceDriveLetter = getDriveLetter(sourcePath, &sourcePathWithoutDrive);
132     // Error if we have a drive letter and it is a remote path
133     if (sourceDriveLetter != '\0' && sourceHost.size() != 0)
134       throw RunTimeException(string("Invalid path: ") + sourcePath + " for host " + sourceHost);
135
136     // Extract the drive letter from the destination path
137     string destinationPathWithoutDrive;
138     char destinationDriveLetter = getDriveLetter(destinationPath, &destinationPathWithoutDrive);
139     // Error if we have a drive letter and it is a remote path
140     if (destinationDriveLetter != '\0' && destinationHost.size() != 0)
141       throw RunTimeException(string("Invalid path: ") + destinationPath + " for host " + destinationHost);
142
143     // Error if we have two drive letters and they are different
144     if (sourceDriveLetter != '\0' && destinationDriveLetter != '\0' &&
145         sourceDriveLetter != destinationDriveLetter)
146       throw RunTimeException(string("Can't use RCP to copy files between different drives: ") +
147                              sourcePath + (", ") + destinationPath);
148
149     // Now get the drive letter to use if there is one
150     char driveLetter = (sourceDriveLetter != '\0') ? sourceDriveLetter : destinationDriveLetter;
151
152     // Get the drive of the current working directory
153     char cwd[_MAX_PATH];
154     _getcwd(cwd, _MAX_PATH);
155     char currentDrive = getDriveLetter(cwd);
156
157     // Change working directory if necessary
158     if (driveLetter != '\0' && driveLetter != currentDrive) {
159       char newdir[3];
160       newdir[0] = driveLetter;
161       newdir[1] = ':';
162       newdir[2] = '\0';
163       cout << "Changing directory: " << newdir << endl;
164       _chdir(newdir);
165     }
166
167     int status = CommunicationProtocol::copyFile(sourcePathWithoutDrive, sourceHost, sourceUser,
168                                                  destinationPathWithoutDrive, destinationHost, destinationUser);
169
170     // Go back to previous directory if necessary
171     if (driveLetter != '\0' && driveLetter != currentDrive) {
172       cout << "Changing directory: " << cwd << endl;
173       _chdir(cwd);
174     }
175
176     return status;
177   }
178
179   char CommunicationProtocolRSH::getDriveLetter(const string & path, string * pathWithoutDrive) const
180   {
181     if (path.find(':') != string::npos) {
182       // Error if the colon is not the second character
183       if (path.size() < 2 || path[1] != ':')
184         throw RunTimeException(string("Invalid path: ") + path);
185       else {
186         if (pathWithoutDrive != NULL) *pathWithoutDrive = path.substr(2);
187         return path[0];
188       }
189     } else {
190       if (pathWithoutDrive != NULL) *pathWithoutDrive = path;
191       return '\0';
192     }
193   }
194
195 #endif
196
197 }