rcopier.C 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  6. * These libraries and programs are free software; you can
  7. * redistribute them and/or modify them under the terms of the GNU
  8. * Lesser General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option)
  10. * any later version.
  11. *
  12. * These libraries and programs are distributed in the hope that
  13. * they will be useful, but WITHOUT ANY WARRANTY; without even the
  14. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15. * PURPOSE. See the GNU Lesser General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with these libraries and programs; if not, write
  20. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  21. * Floor, Boston, MA 02110-1301 USA
  22. */
  23. //%% (c) Copyright 1993, 1994 Hewlett-Packard Company
  24. //%% (c) Copyright 1993, 1994 International Business Machines Corp.
  25. //%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
  26. //%% (c) Copyright 1993, 1994 Novell, Inc.
  27. //%% $XConsortium: rcopier.C /main/3 1995/10/20 16:36:32 rswiston $
  28. /*
  29. * rcopier.cc - Link Service/ToolTalk wrapper for rcp(1).
  30. *
  31. * Copyright (c) 1990 by Sun Microsystems, Inc.
  32. *
  33. */
  34. #include "tt_options.h"
  35. #include <string.h>
  36. #include <osfcn.h>
  37. #if defined(OPT_BUG_SUNOS_4)
  38. # include <stdlib.h>
  39. #endif
  40. #include <Tt/tt_c.h>
  41. #include <util/tt_path.h>
  42. #include <util/tt_enumname.h>
  43. #include <util/copyright.h>
  44. #include "rcopier.h"
  45. /*
  46. * External variables
  47. */
  48. implement_list_of(rpath)
  49. /*
  50. * rpath::rpath()
  51. */
  52. rpath::
  53. rpath()
  54. {
  55. }
  56. /*
  57. * rpath::~rpath()
  58. */
  59. rpath::
  60. ~rpath()
  61. {
  62. }
  63. /*
  64. * rpath::rpath()
  65. */
  66. rpath::
  67. rpath( _Tt_string)
  68. {
  69. /*
  70. * host:path
  71. * user@host:path
  72. */
  73. }
  74. /*
  75. * rcopier::rcopier()
  76. */
  77. rcopier::
  78. rcopier( char *arg0 )
  79. {
  80. if (arg0 != NULL) {
  81. char *base = strrchr( arg0, '/' );
  82. if (base == NULL) {
  83. base = arg0;
  84. } else {
  85. base++; /* Don't want the '/' */
  86. }
  87. _prog_name = base;
  88. _process_name = _prog_name;
  89. }
  90. _args = new _Tt_string_list();
  91. _from_paths = new rpath_list();
  92. _should_rcp = TRUE;
  93. _recurse = FALSE;
  94. _preserve = FALSE;
  95. _tt_opened = FALSE;
  96. }
  97. rcopier::
  98. ~rcopier()
  99. {
  100. }
  101. /*
  102. * rcopier::do_rcp() - Use system() to invoke rcp(1), and return its exit status.
  103. * We can just use _args, since we never get here when our one
  104. * rcp-incompatible option (-L) has been given.
  105. */
  106. int rcopier::
  107. do_rcp()
  108. {
  109. _Tt_string cmd( "rcp" );
  110. _Tt_string_list_cursor arg_cursor( _args );
  111. while (arg_cursor.next()) {
  112. cmd = cmd.cat( " " ).cat( *arg_cursor );
  113. }
  114. printf( "Invoking: %s\n", (char *)cmd );
  115. int sys_status = system( (char *)cmd );
  116. if (WIFEXITED(sys_status)) {
  117. return WEXITSTATUS(sys_status);
  118. } else {
  119. fprintf( stderr,
  120. "%s: I invoked rcp(1), but system() returned "
  121. "%d, which is not an exit status!\n",
  122. (char *)_process_name, sys_status );
  123. return 1;
  124. }
  125. }
  126. /*
  127. * rcopier::do_ttrcp() - Use tttar(1) to copy the objects of the _from_paths.
  128. *
  129. * Algorithm:
  130. *
  131. * [rsh fromhost -l user] tttar cfhL - frompath |
  132. * [rsh tohost -l user] tttar xfL - -rename frompath topath
  133. *
  134. * TO_DO: this won't work if topath is a directory. If it's a
  135. * remote directory, how do we find this out?
  136. * }
  137. */
  138. Tt_status rcopier::
  139. do_ttrcp()
  140. {
  141. rpath_list_cursor from_path_cursor( _from_paths );
  142. /*
  143. * TO_DO: tt_file_destroy() any paths that rcp(1) will delete
  144. */
  145. while (from_path_cursor.next()) {
  146. _Tt_string cmd;
  147. rpath_ptr rp = *from_path_cursor;
  148. if (rp->host().len() >= 0) {
  149. cmd = cmd.cat( "rsh ").cat( rp->host()).cat( " -l ")
  150. .cat( _username ).cat( " " );
  151. }
  152. cmd = cmd.cat( "tttar cfhL - " ).cat( rp->path()).cat(" | ");
  153. if (_to_path->host().len() >= 0) {
  154. cmd = cmd.cat( "rsh ").cat( _to_path->host())
  155. .cat( " -l ").cat( _username ).cat( " " );
  156. }
  157. cmd = cmd.cat( "tttar xfL" );
  158. if (_preserve) {
  159. cmd = cmd.cat( "p" );
  160. }
  161. cmd = cmd.cat( " - -rename " ).cat( rp->path())
  162. .cat( _to_path->path());
  163. printf( "Invoking: %s\n", (char *)cmd );
  164. int sys_status = system( (char *)cmd );
  165. if (WIFEXITED(sys_status)) {
  166. if (WEXITSTATUS(sys_status) != 0) {
  167. return TT_ERR_INTERNAL;
  168. }
  169. } else {
  170. fprintf( stderr,
  171. "%s: invoked tttar(1), but system() returned "
  172. "%d, which is not an exit status!\n",
  173. (char *)_process_name, sys_status );
  174. return TT_ERR_INTERNAL;
  175. }
  176. }
  177. return TT_OK;
  178. } /* do_ttrcp() */
  179. /*
  180. * rcopier::open_tt()
  181. */
  182. Tt_status rcopier::
  183. open_tt()
  184. {
  185. char *process_id = tt_open();
  186. Tt_status err = tt_ptr_error( process_id );
  187. if (err == TT_OK) {
  188. _process_id = process_id;
  189. _tt_opened = TRUE;
  190. } else if (err > TT_WRN_LAST) {
  191. fprintf( stderr,
  192. "%s: Could not initialize ToolTalk because %s\n",
  193. (char *)_process_name,
  194. #ifndef TT_STATUS_MSG_TO_DO
  195. _tt_enumname( (Tt_status)err )
  196. #else
  197. tt_status_message( err )
  198. #endif
  199. );
  200. }
  201. return err;
  202. }
  203. /*
  204. * rcopier::close_tt()
  205. */
  206. Tt_status rcopier::
  207. close_tt()
  208. {
  209. if (! _tt_opened) {
  210. return TT_OK;
  211. }
  212. Tt_status err = tt_close();
  213. if (err > TT_WRN_LAST) {
  214. fprintf( stderr,
  215. "%s: Could not close ToolTalk because %s\n",
  216. (char *)_process_name,
  217. #ifndef TT_STATUS_MSG_TO_DO
  218. _tt_enumname( (Tt_status)err )
  219. #else
  220. tt_status_message( err )
  221. #endif
  222. );
  223. }
  224. return err;
  225. }
  226. /*
  227. * rcopier::parse_args()
  228. */
  229. void rcopier::
  230. parse_args( int argc, char **argv )
  231. {
  232. for ( int arg_num = 1; arg_num < argc; arg_num++ ) {
  233. _Tt_string arg( argv[arg_num] );
  234. _args->append( arg );
  235. if (arg[0] == '-') {
  236. this->_parse_arg( (char *)arg );
  237. } else {
  238. if (arg_num == argc - 1) {
  239. _to_path = new rpath( arg );
  240. } else {
  241. rpath_ptr rp = new rpath( arg );
  242. _from_paths->append( rp );
  243. }
  244. }
  245. }
  246. if (_to_path->path().len() <= 0) {
  247. this->usage();
  248. exit(1);
  249. }
  250. if (_from_paths->count() <= 0) {
  251. this->usage();
  252. exit(1);
  253. }
  254. if (_from_paths->count() > 1) {
  255. /*
  256. * If multiple things to move, the place we're
  257. * moving them to must be a directory.
  258. */
  259. if (_to_path->host().len() <= 0) {
  260. /*
  261. * to_path is local. Yay!
  262. */
  263. struct stat stat_buf;
  264. if (stat( (char *)_to_path->path(), &stat_buf) != 0) {
  265. fprintf( stderr, "%s: %s: ",
  266. (char *)_process_name,
  267. (char *)_to_path->path() );
  268. perror(NULL);
  269. exit(2);
  270. }
  271. if (! S_ISDIR(stat_buf.st_mode)) {
  272. fprintf( stderr, "%s: %s is not a directory\n",
  273. (char *)_process_name,
  274. (char *)_to_path->path() );
  275. this->usage();
  276. exit(2);
  277. }
  278. _to_path_is_dir = TRUE;
  279. } else {
  280. /*
  281. * TO_DO: figure out if remote path is dir or not
  282. */
  283. }
  284. } else {
  285. if (_to_path->host().len() <= 0) {
  286. struct stat stat_buf;
  287. _to_path_is_dir = FALSE;
  288. if (stat( (char *)_to_path->path(), &stat_buf) == 0) {
  289. _to_path_is_dir = S_ISDIR(stat_buf.st_mode);
  290. }
  291. /*
  292. * I don't think rcp has a clonedir mode. (see ttcp)
  293. else {
  294. _Tt_string from_path = _from_paths->top();
  295. if ( (_from_paths->count() == 1)
  296. && (stat( (char *)from_path, &stat_buf) == 0)
  297. && S_ISDIR(stat_buf.st_mode))
  298. {
  299. _clonedir_mode = TRUE;
  300. _to_path_is_dir = TRUE;
  301. }
  302. }
  303. */
  304. } else {
  305. /*
  306. * TO_DO: figure out if remote path is dir or not
  307. */
  308. }
  309. }
  310. } /* parse_args() */
  311. /*
  312. * rcopier::_parse_arg() - Parse an option
  313. */
  314. void rcopier::
  315. _parse_arg( char *arg )
  316. {
  317. if (arg == NULL) {
  318. return;
  319. }
  320. int n = -1;
  321. while (arg[++n] != '\0') {
  322. switch (arg[n]) {
  323. case '-':
  324. if (n != 0) {
  325. this->usage();
  326. exit(1);
  327. }
  328. break;
  329. case 'L':
  330. _should_rcp = FALSE;
  331. break;
  332. case 'p':
  333. _preserve = TRUE;
  334. break;
  335. case 'r':
  336. _recurse = TRUE;
  337. break;
  338. case 'v':
  339. _TT_PRINT_VERSIONS((char *)_prog_name)
  340. exit(0);
  341. break;
  342. case 'h':
  343. default:
  344. this->usage();
  345. exit(1);
  346. }
  347. }
  348. } /* _parse_arg() */
  349. /*
  350. * rcopier::usage()
  351. */
  352. void rcopier::
  353. usage(FILE *fs) const
  354. {
  355. fprintf( fs,
  356. "Usage: %s [-pL] file1 file2\n"
  357. " %s [-prL] path1 [path2 ...] dir\n"
  358. " %s -v\n"
  359. " %s -h\n",
  360. (char *)_prog_name, (char *)_prog_name, (char *)_prog_name,
  361. (char *)_prog_name );
  362. fprintf( fs, "\t-L do not perform a rcp(1)\n" );
  363. fprintf( fs, "\t-v print the version number and quit\n" );
  364. fprintf( fs, "\t-h[elp] print this message\n" );
  365. }