00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "vsl_rcp.h"
00014 #include "vsl_api.h"
00015 #include <sys/types.h>
00016 #include <sys/stat.h>
00017 #include <unistd.h>
00018 #include "vsl.h"
00019 #include <pwd.h>
00020 #include <strings.h>
00021 #include <string.h>
00022 #include <stdlib.h>
00023 #include <stdio.h>
00024 #include <fcntl.h>
00025 #include <signal.h>
00026 #include "vfer.h"
00027
00028
00029
00030
00031 typedef struct vsl_rcp_info {
00032 char local_path[MAX_PATH];
00033 char remote_path[MAX_PATH];
00034 char cmd[MAX_PATH];
00035 char user[MAX_USER];
00036 char host[MAX_HOST];
00037 char from_remote;
00038
00039 char logfile[MAX_PATH];
00040 int debug;
00041 } vsl_rcp_info;
00042
00043
00044
00045 void print_help (char* prog, int verbose);
00046 int parse_opts (int argc, char** argv, vsl_rcp_info *t);
00047
00048
00049
00050
00051
00052
00053
00054
00055 void print_help(char* prog, int verbose) {
00056 printf("usage: %s [-h] [-v[v]] [-c path_to_rcpd] [[user1@]host1:]file1 [[user2@]host2:]file2\n", prog);
00057 if (verbose == 0) return;
00058 printf("\t-h brings up this help page [optional]\n");
00059 printf("\t-v verbose message printing [optional]\n");
00060 printf("\t-vv even more verbose message printing [optional]\n");
00061 printf("\t-l only in combination with -v. Specifies the (remote) filename\n"
00062 "\t where the server writes its debug output to. Defaults to\n"
00063 "\t " DEBUGLOG "\t\t [optional]\n");
00064 printf("\t-c pathname of vsl_rcpd on remote host [optional]\n");
00065 printf("\tuser[1,2] username to use when connecting to host [optional]\n");
00066 printf("\thost[1,2] hostname of remote system\n");
00067 printf("\tfile[1,2] local, remote file path\n");
00068 printf("notes:\n");
00069 printf("\t- one remote host is required (signaled with ':')\n");
00070 printf("\t- username is defauled to user invoking the program\n");
00071 printf("\t- remote->remote copying is not implemented\n");
00072 }
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088 int parse_opts(int argc, char** argv, vsl_rcp_info* info) {
00089 int c;
00090 char* r;
00091 char* l;
00092 char *cp, *cp2;
00093 struct passwd *pwentry;
00094 int uid;
00095
00096
00097 extern char *optarg;
00098 extern int optind;
00099 extern int optopt;
00100 extern int opterr;
00101
00102 opterr=0;
00103 bzero(info->local_path, MAX_PATH);
00104 bzero(info->remote_path, MAX_PATH);
00105 bzero(info->user, MAX_USER);
00106 bzero(info->host, MAX_HOST);
00107 strncpy(info->cmd, "vsl_rcpd", MAX_PATH);
00108 info->debug = 0;
00109 strncpy(info->logfile, DEBUGLOG, MAX_PATH);
00110 while (1) {
00111 c = getopt (argc, argv, ":hc:l:v");
00112 if (c == -1) break;
00113 switch (c) {
00114 case 'h':
00115 return -2;
00116 break;
00117 case 'c':
00118 strncpy(info->cmd, optarg, MAX_PATH);
00119 break;
00120 case 'l':
00121 strncpy(info->logfile, optarg, MAX_PATH);
00122 break;
00123 case 'v':
00124 if (info->debug == 0) {
00125 vsl_debug(stderr, NULL);
00126 info->debug=1;
00127 }
00128 else {
00129 vsl_debug(stderr, "pacC");
00130 info->debug=2;
00131 }
00132 break;
00133 case ':':
00134 fprintf(stderr, "option %c missing value\n", optopt);
00135 return -1;
00136 case '?':
00137 fprintf(stderr, "unknown option: %c\n", optopt);
00138 return -1;
00139 default:
00140 fprintf(stderr, "getopt returned character code 0%o\n", c);
00141 return -1;
00142 }
00143 }
00144 if (argc - optind != 2) {
00145 fprintf(stderr, "exactly two non-option args required\n");
00146 return -1;
00147 }
00148
00149
00150 cp = index(argv[optind], ':');
00151 cp2 = index(argv[optind+1], ':');
00152 if (cp != NULL && cp2 != NULL) {
00153 fprintf(stderr, "one of file paths must be local\n");
00154 return -1;
00155 } else if (cp == NULL && cp2 == NULL) {
00156 fprintf(stderr, "one of file paths must be remote\n");
00157 return -1;
00158 }
00159
00160
00161 if (cp != NULL) {
00162 if (cp == argv[optind]) {
00163 fprintf(stderr, "no hostname specified for remote path\n");
00164 return -1;
00165 }
00166 info->from_remote = 0;
00167 r=argv[optind];
00168 l=argv[optind+1];
00169 } else {
00170 if (cp2 == argv[optind+1]) {
00171 fprintf(stderr, "no hostname specified for remote path\n");
00172 return -1;
00173 }
00174 info->from_remote = 1;
00175 l=argv[optind];
00176 r=argv[optind+1];
00177 }
00178
00179
00180 strncpy(info->local_path, l, MAX_PATH);
00181
00182
00183
00184 cp = index(r, ':');
00185 if (strlen(r) - 1 + r == cp) {
00186
00187 strcpy(info->remote_path, "~/");
00188 } else {
00189 strncpy(info->remote_path, cp+1, MAX_PATH);
00190 }
00191
00192
00193 cp2 = index(r, '@');
00194 if (cp2 == NULL) {
00195
00196
00197
00198 uid=getuid();
00199 if ((pwentry = getpwuid(uid)) == NULL) {
00200 fprintf(stderr, "failed getting password entry for uid(%d)\n", uid);
00201 return -1;
00202 }
00203 if (strlen(pwentry->pw_name) > MAX_USER) {
00204 fprintf(stderr, "length of username must be less than %d\n", MAX_USER);
00205 return -1;
00206 }
00207 strncpy(info->user, pwentry->pw_name, MAX_USER);
00208
00209 if (cp - r > MAX_HOST) {
00210 fprintf(stderr, "length of hostname must be less than %d\n", MAX_HOST);
00211 return -1;
00212 }
00213 strncpy(info->host, r, cp - r);
00214 } else {
00215 if (cp2 > cp) {
00216 fprintf(stderr, "'@' must come before ':'\n");
00217 return -1;
00218 } else if (cp2 + 1 == cp) {
00219 fprintf(stderr, "no hostname specified for remote path\n");
00220 return -1;
00221 } else if (cp2 == r) {
00222 fprintf(stderr, "missing username for remote path\n");
00223 return -1;
00224 }
00225
00226 if (cp - cp2 > MAX_HOST) {
00227 fprintf(stderr, "length of hostname must be less than %d\n", MAX_HOST);
00228 return -1;
00229 }
00230 strncpy(info->host, cp2+1, cp - cp2 - 1);
00231
00232 if (cp2 - r > MAX_USER) {
00233 fprintf(stderr, "length of username must be less than %d\n", MAX_USER);
00234 return -1;
00235 }
00236 strncpy(info->user, r, cp2 - r);
00237 }
00238
00239
00240 if (info->local_path[strlen(info->local_path) - 1] == '/') {
00241 cp = rindex(info->remote_path, '/');
00242 strncpy(info->local_path + strlen(info->local_path), cp+1, MAX_PATH - strlen(info->local_path));
00243 }
00244
00245 return 0;
00246 }
00247
00248
00249
00250
00251
00252 void sig_handler(int sig) {
00253 exit(1);
00254 }
00255
00256
00257
00258
00259 int main (int argc, char **argv) {
00260 int ret;
00261
00262
00263 vsl_rcp_info info;
00264 if (argc == 1) {
00265 print_help(argv[0], 0);
00266 return 0;
00267 }
00268 if ( (ret = parse_opts(argc, argv, &info)) == -2) {
00269 print_help(argv[0], 1);
00270 return 0;
00271 } else if (ret == -1) {
00272 print_help(argv[0], 0);
00273 return -1;
00274 }
00275
00276
00277 vsl_client_msg_t client_msg;
00278 int fd;
00279 char *c;
00280 strncpy(client_msg.remote_path, info.remote_path, MAX_PATH);
00281 client_msg.from_remote = info.from_remote;
00282 if ((c = rindex(info.local_path, '/')) == NULL) {
00283 strncpy(client_msg.local_name, info.local_path, MAX_PATH);
00284 } else {
00285 strncpy(client_msg.local_name, c+1, MAX_PATH);
00286 }
00287 if (info.from_remote == 1) {
00288 if ((fd = open(info.local_path, O_RDONLY)) == -1) {
00289 fprintf(stderr, "couldn't open local file [%s] for reading\n", info.local_path);
00290 exit(1);
00291 }
00292 client_msg.file_size = lseek(fd, 0, SEEK_END);
00293 close(fd);
00294 } else {
00295 client_msg.file_size = 0;
00296 }
00297
00298
00299 vsl_sock sock;
00300 vfer_fd vfd;
00301 if ( (ret = vsl_init()) != 0) {
00302 fprintf(stderr, "cannot init vsl: %s!\n", vsl_errortext(ret));
00303 exit(1);
00304 }
00305 if ( (vfd = vfer_socket(SOCK_DGRAM)) < 0) {
00306 fprintf(stderr, "vfer_socket failed: %s!\n", vfer_errortext(vfd));
00307 exit(1);
00308 }
00309 if ( (ret = vsl_socket(&sock, vfd)) != 0) {
00310 fprintf(stderr, "vsl_socket failed: %s!\n", vsl_errortext(ret));
00311 exit(1);
00312 }
00313
00314
00315 char errmsg[512] = "";
00316 int s_argc = 1;
00317 const char* s_argv[3];
00318 s_argv[0] = MAGIC_PARM;
00319 if ( info.debug > 0 ) {
00320 s_argc = 2;
00321 s_argv[1] = info.logfile;
00322 }
00323 if ( info.debug > 1 ) {
00324 s_argc = 3;
00325 s_argv[2] = "paCc";
00326 }
00327 if ( (ret = vsl_connect_ssh(&sock, info.host, info.user,
00328 info.cmd, s_argc, s_argv,
00329 errmsg)) != 0) {
00330 fprintf(stderr, "vsl_connect_ssh failed: %s!\n", vsl_errortext(ret));
00331 fprintf(stderr, "server said: %s!\n", errmsg);
00332 exit(1);
00333 }
00334
00335
00336 struct sigaction sa;
00337 sa.sa_handler = &(sig_handler);
00338 if (sigaction(SIGINT, &sa, NULL) == -1)
00339 LOG("couldn't install a signal handler for SIGINT");
00340
00341
00342 client_msg.file_size = htonl(client_msg.file_size);
00343 if ((ret = vsl_send(&sock, &client_msg, sizeof(vsl_client_msg_t))) < 0) {
00344 fprintf(stderr, "send client msg failed [%s]\n", vsl_errortext(ret));
00345 goto CLEAN_UP_NO_STAT;
00346 }
00347 client_msg.file_size = ntohl(client_msg.file_size);
00348
00349
00350 vsl_server_msg_t server_msg;
00351 if ((ret = vsl_recv(&sock, &server_msg, sizeof(vsl_server_msg_t))) < 0) {
00352 fprintf(stderr, "receive server msg failed [%s]\n", vsl_errortext(ret));
00353 goto CLEAN_UP_NO_STAT;
00354 }
00355 server_msg.file_size = ntohl(server_msg.file_size);
00356 server_msg.status = ntohl(server_msg.status);
00357
00358 switch (server_msg.status) {
00359 case RCP_READY:
00360 if (info.from_remote == 0) {
00361
00362 if ((fd = open(info.local_path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)) == -1) {
00363 perror("open for writing failed");
00364 goto CLEAN_UP_NO_STAT;
00365 }
00366 if ((ret = vsl_recvfile(&sock, fd, 0, server_msg.file_size)) < 0)
00367 fprintf(stderr,"vfer_recvfile failed [%s]\n", vsl_errortext(ret));
00368
00369 } else {
00370
00371 if ((fd = open(info.local_path, O_RDONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)) == -1) {
00372 perror("open for reading failed");
00373 goto CLEAN_UP_NO_STAT;
00374 }
00375
00376 if ((ret = vsl_sendfile(&sock, fd, 0, client_msg.file_size)) < 0)
00377 fprintf(stderr, "vfer_sendfile failed [%s]\n", vsl_errortext(ret));
00378 }
00379 goto CLEAN_UP_STAT;
00380
00381 case RCP_ENOENT:
00382 fprintf(stderr, "component of the path does not exist on remote file system\n");
00383 break;
00384
00385 case RCP_EOPEN:
00386 if (info.from_remote == 0) {
00387 fprintf(stderr, "can't open remote file for reading\n");
00388 } else {
00389 fprintf(stderr, "can't open remote file for writing\n");
00390 }
00391 break;
00392
00393 case RCP_ENOFILE:
00394 fprintf(stderr, "file doesn't exist on remote host\n");
00395 break;
00396
00397 case RCP_EUSER:
00398 fprintf(stderr, "wrong username specified for remote host\n");
00399 break;
00400
00401 case RCP_EOTHER:
00402 fprintf(stderr, "unspecified remote error\n");
00403 break;
00404
00405 default:
00406 fprintf(stderr, "could not interpret server msg code\n");
00407 break;
00408 }
00409
00410 CLEAN_UP_NO_STAT:
00411 vsl_close(&sock);
00412 vsl_uninit();
00413 close(fd);
00414 return 0;
00415
00416 CLEAN_UP_STAT:
00417 ;
00418 vfer_stats stats;
00419 stats = vfer_sockstats(vsl_vferfd(&sock));
00420 if ( info.debug )
00421 vfer_rcp_print_stats(&stats);
00422 vsl_close(&sock);
00423 vfer_close(vfd);
00424 vsl_uninit();
00425 close(fd);
00426 return 0;
00427 }
00428
00429
00430
00431
00432
00433
00434
00435