Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / lib / tt / bin / shell / rcopier.C
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 librararies 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
35 #include "tt_options.h"
36 #include <string.h>
37 #ifdef __osf__
38 #include <unistd.h>
39 #else
40 #ifndef USL
41 #include <osfcn.h>
42 #endif
43 #endif
44 #if defined(OPT_BUG_SUNOS_4)
45 #       include <stdlib.h>
46 #endif
47 #include <api/c/tt_c.h>
48 #include <util/tt_path.h>
49 #include <util/tt_enumname.h>
50 #include <util/copyright.h>
51 #include "rcopier.h"
52
53 /*
54  * External variables
55  */
56
57 implement_list_of(rpath)
58
59 /*
60  * rpath::rpath()
61  */
62 rpath::
63 rpath()
64 {
65 }
66
67 /*
68  * rpath::~rpath()
69  */
70 rpath::
71 ~rpath()
72 {
73 }
74
75 /*
76  * rpath::rpath()
77  */
78 rpath::
79 rpath( _Tt_string)
80 {
81         /*
82          * host:path
83          * user@host:path
84          */
85 }
86
87 /*
88  * rcopier::rcopier()
89  */
90 rcopier::
91 rcopier( char *arg0 )
92 {
93         if (arg0 != NULL) {
94                 char *base = strrchr( arg0, '/' );
95                 if (base == NULL) {
96                         base = arg0;
97                 } else {
98                         base++; /* Don't want the '/' */
99                 }
100                 _prog_name = base;
101                 _process_name = _prog_name;
102         }
103         _args = new _Tt_string_list();
104         _from_paths = new rpath_list();
105         _should_rcp = TRUE;
106         _recurse = FALSE;
107         _preserve = FALSE;
108         _tt_opened = FALSE;
109 }
110
111 rcopier::
112 ~rcopier()
113 {
114 }
115
116 /*
117  * rcopier::do_rcp() - Use system() to invoke rcp(1), and return its exit status.
118  *      We can just use _args, since we never get here when our one
119  *      rcp-incompatible option (-L) has been given.
120  */
121 int rcopier::
122 do_rcp()
123 {
124         _Tt_string              cmd( "rcp" );
125         _Tt_string_list_cursor  arg_cursor( _args );
126
127         while (arg_cursor.next()) {
128                 cmd = cmd.cat( " " ).cat( *arg_cursor );
129         }
130         printf( "Invoking: %s\n", (char *)cmd );
131         int sys_status = system( (char *)cmd );
132         if (WIFEXITED(sys_status)) {
133                 return WEXITSTATUS(sys_status);
134         } else {
135                 fprintf( stderr,
136                          "%s: I invoked rcp(1), but system() returned "
137                          "%d, which is not an exit status!\n",
138                          (char *)_process_name, sys_status );
139                 return 1;
140         }
141 }
142
143 /*
144  * rcopier::do_ttrcp() - Use tttar(1) to copy the objects of the _from_paths.
145  *
146  * Algorithm:
147  *
148  * [rsh fromhost -l user] tttar cfhL - frompath |
149  * [rsh tohost -l user] tttar xfL - -rename frompath topath
150  *
151  * TO_DO: this won't work if topath is a directory.  If it's a
152  * remote directory, how do we find this out?
153  * }
154  */
155 Tt_status rcopier::
156 do_ttrcp()
157 {
158         rpath_list_cursor       from_path_cursor( _from_paths );
159
160         /*
161          * TO_DO: tt_file_destroy() any paths that rcp(1) will delete
162          */
163         while (from_path_cursor.next()) {
164                 _Tt_string      cmd;
165                 rpath_ptr       rp = *from_path_cursor;
166
167                 if (rp->host().len() >= 0) {
168                         cmd = cmd.cat( "rsh ").cat( rp->host()).cat( " -l ")
169                                  .cat( _username ).cat( " " );
170                 }
171                 cmd = cmd.cat( "tttar cfhL - " ).cat( rp->path()).cat(" | ");
172                 if (_to_path->host().len() >= 0) {
173                         cmd = cmd.cat( "rsh ").cat( _to_path->host())
174                                  .cat( " -l ").cat( _username ).cat( " " );
175                 }
176                 cmd = cmd.cat( "tttar xfL" );
177                 if (_preserve) {
178                         cmd = cmd.cat( "p" );
179                 }
180                 cmd = cmd.cat( " - -rename " ).cat( rp->path())
181                          .cat( _to_path->path());
182                 printf( "Invoking: %s\n", (char *)cmd );
183                 int sys_status = system( (char *)cmd );
184                 if (WIFEXITED(sys_status)) {
185                         if (WEXITSTATUS(sys_status) != 0) {
186                                 return TT_ERR_INTERNAL;
187                         }
188                 } else {
189                         fprintf( stderr,
190                                  "%s: invoked tttar(1), but system() returned "
191                                  "%d, which is not an exit status!\n",
192                                  (char *)_process_name, sys_status );
193                         return TT_ERR_INTERNAL;
194                 }
195         }
196         return TT_OK;
197
198 } /* do_ttrcp() */
199
200 /*
201  * rcopier::open_tt()
202  */
203 Tt_status rcopier::
204 open_tt()
205 {
206         char *process_id = tt_open();
207         Tt_status err = tt_ptr_error( process_id );
208         if (err == TT_OK) {
209                 _process_id = process_id;
210                 _tt_opened = TRUE;
211         } else if (err > TT_WRN_LAST) {
212                 fprintf( stderr,
213                          "%s: Could not initialize ToolTalk because %s\n",
214                          (char *)_process_name,
215 #ifndef TT_STATUS_MSG_TO_DO
216                          _tt_enumname( (Tt_status)err )
217 #else
218                          tt_status_message( err )
219 #endif
220                        );
221         }
222         return err;
223 }
224
225 /*
226  * rcopier::close_tt()
227  */
228 Tt_status rcopier::
229 close_tt()
230 {
231         if (! _tt_opened) {
232                 return TT_OK;
233         }
234         Tt_status err = tt_close();
235         if (err > TT_WRN_LAST) {
236                 fprintf( stderr,
237                          "%s: Could not close ToolTalk because %s\n",
238                          (char *)_process_name,
239 #ifndef TT_STATUS_MSG_TO_DO
240                          _tt_enumname( (Tt_status)err )
241 #else
242                          tt_status_message( err )
243 #endif
244                        );
245         }
246         return err;
247 }
248
249 /*
250  * rcopier::parse_args()
251  */
252 void rcopier::
253 parse_args( int argc, char **argv )
254 {
255         for ( int arg_num = 1; arg_num < argc; arg_num++ ) {
256                 _Tt_string arg( argv[arg_num] );
257                 _args->append( arg );
258                 if (arg[0] == '-') {
259                         this->_parse_arg( (char *)arg );
260                 } else {
261                         if (arg_num == argc - 1) {
262                                 _to_path = new rpath( arg );
263                         } else {
264                                 rpath_ptr rp = new rpath( arg );
265                                 _from_paths->append( rp );
266                         }
267                 }
268         }
269         if (_to_path->path().len() <= 0) {
270                 this->usage();
271                 exit(1);
272         }
273         if (_from_paths->count() <= 0) {
274                 this->usage();
275                 exit(1);
276         }
277         if (_from_paths->count() > 1) {
278                 /*
279                  * If multiple things to move, the place we're
280                  * moving them to must be a directory.
281                  */
282                 if (_to_path->host().len() <= 0) {
283                         /*
284                          * to_path is local.  Yay!
285                          */
286                         struct stat stat_buf;
287
288                         if (stat( (char *)_to_path->path(), &stat_buf) != 0) {
289                                 fprintf( stderr, "%s: %s: ",
290                                          (char *)_process_name,
291                                          (char *)_to_path->path() );
292                                 perror(NULL);
293                                 exit(2);
294                         }
295                         if (! S_ISDIR(stat_buf.st_mode)) {
296                                 fprintf( stderr, "%s: %s is not a directory\n",
297                                          (char *)_process_name,
298                                          (char *)_to_path->path() );
299                                 this->usage();
300                                 exit(2);
301                         }
302                         _to_path_is_dir = TRUE;
303                 } else {
304                         /*
305                          * TO_DO: figure out if remote path is dir or not
306                          */
307                 }
308         } else {
309                 if (_to_path->host().len() <= 0) {
310                         struct stat stat_buf;
311
312                         _to_path_is_dir = FALSE;
313                         if (stat( (char *)_to_path->path(), &stat_buf) == 0) {
314                                 _to_path_is_dir = S_ISDIR(stat_buf.st_mode);
315                         } 
316                         /*
317                          * I don't think rcp has a clonedir mode. (see ttcp)
318                         else {
319                                 _Tt_string from_path = _from_paths->top();
320                                 if (    (_from_paths->count() == 1)
321                                      && (stat( (char *)from_path, &stat_buf) == 0)
322                                      && S_ISDIR(stat_buf.st_mode))
323                                 {
324                                         _clonedir_mode = TRUE;
325                                         _to_path_is_dir = TRUE;
326                                 }
327                         }
328                          */
329                 } else {
330                         /*
331                          * TO_DO: figure out if remote path is dir or not
332                          */
333                 }
334         }
335
336 } /* parse_args() */
337
338 /*
339  * rcopier::_parse_arg() - Parse an option 
340  */
341 void rcopier::
342 _parse_arg( char *arg )
343 {
344         if (arg == NULL) {
345                 return;
346         }
347         int n = -1;
348         while (arg[++n] != '\0') {
349                 switch (arg[n]) {
350                     case '-':
351                         if (n != 0) {
352                                 this->usage();
353                                 exit(1);
354                         }
355                         break;
356                     case 'L':
357                         _should_rcp = FALSE;
358                         break;
359                     case 'p':
360                         _preserve = TRUE;
361                         break;
362                     case 'r':
363                         _recurse = TRUE;
364                         break;
365                     case 'v':
366                         _TT_PRINT_VERSIONS((char *)_prog_name)
367                         exit(0);
368                         break;
369                     case 'h':
370                     default:
371                         this->usage();
372                         exit(1);
373                 }
374         }
375 } /* _parse_arg() */
376
377 /*
378  * rcopier::usage()
379  */
380 void rcopier::
381 usage(FILE *fs) const
382 {
383         fprintf( fs,
384                  "Usage: %s [-pL] file1 file2\n"
385                  "       %s [-prL] path1 [path2 ...] dir\n"
386                  "       %s -v\n"
387                  "       %s -h\n",
388                  (char *)_prog_name, (char *)_prog_name, (char *)_prog_name,
389                  (char *)_prog_name );
390         fprintf( fs, "\t-L      do not perform a rcp(1)\n" );
391         fprintf( fs, "\t-v      print the version number and quit\n" );
392         fprintf( fs, "\t-h[elp] print this message\n" );
393 }