Esempio n. 1
0
/* store a local file on remote server */
void cmd_put(int argc, char **argv)
{
	int c, opt=PUT_VERBOSE;
	list *gl;
	char *put_output = 0;
	char *logfile = 0;
	pid_t pid;
#ifdef HAVE_REGEX
	int ret;
	char put_rx_errbuf[129];
#endif
	struct option longopts[] = {
		{"append", no_argument, 0, 'a'},
		{"delete-after", no_argument, 0, 'D'},
		{"dir-mask", required_argument, 0, '3'},
#ifdef HAVE_REGEX
		{"dir-rx-mask", required_argument, 0, '4'},
#endif
		{"skip-empty", no_argument, 0, 'e'},
		{"force", no_argument, 0, 'f'},
		{"nohup", no_argument, 0, 'H'},
		{"interactive", no_argument, 0, 'i'},
		{"logfile", required_argument, 0, 'L'},
		{"mask", required_argument, 0, 'm'},
#ifdef HAVE_REGEX
		{"rx-mask", required_argument, 0, 'M'},
#endif
		{"newer", no_argument, 0, 'n'},
		{"output", required_argument, 0, 'o'},
		{"preserve", no_argument, 0, 'p'},
		{"parents", no_argument, 0, 'P'},
		{"quiet", no_argument, 0, 'q'},
		{"recursive", no_argument, 0, 'r'},
		{"resume", no_argument, 0, 'R'},
		{"skip-existing", no_argument, 0, 's'},
		{"tagged", no_argument, 0, 't'},
		{"type", required_argument, 0, '1'},
		{"verbose", no_argument, 0, 'v'},
		{"unique", no_argument, 0, 'u'},
		{"help", no_argument, 0, 'h'},
		{0, 0, 0, 0},
	};

	if(put_glob_mask) {
		free(put_glob_mask);
		put_glob_mask = 0;
	}
	if(put_dir_glob_mask) {
		free(put_dir_glob_mask);
		put_dir_glob_mask = 0;
	}
#ifdef HAVE_REGEX
	if(put_rx_mask_set) {
		regfree(&put_rx_mask);
		put_rx_mask_set = 0;
	}
	if(put_dir_rx_mask_set) {
		regfree(&put_dir_rx_mask);
		put_dir_rx_mask_set = 0;
	}
#endif

	put_skip_empty = false;

	optind = 0; /* force getopt() to re-initialize */
	while((c = getopt_long(argc, argv,
						   "aDefHiL:no:pPqrRstvum:M:", longopts, 0)) != EOF)
	{
		switch(c) {
		case 'i':
			opt |= PUT_INTERACTIVE;
			break;
		case 'f':
			opt |= PUT_FORCE;
			break;
		   case 'e':
			  opt |= PUT_SKIP_EMPTY;
			  put_skip_empty = true;
			  break;
		case '3': /* --dir-mask=GLOB */
			free(put_dir_glob_mask);
			put_dir_glob_mask = xstrdup(optarg);
			unquote(put_dir_glob_mask);
			break;
#ifdef HAVE_REGEX
		case '4': /* --dir-rx-mask=REGEXP */
			if(put_dir_rx_mask_set) {
				regfree(&put_dir_rx_mask);
				put_dir_rx_mask_set = false;
			}
			unquote(optarg);
			ret = regcomp(&put_dir_rx_mask, optarg, REG_EXTENDED);
			if(ret != 0) {
				regerror(ret, &put_dir_rx_mask, put_rx_errbuf, 128);
				ftp_err(_("Regexp '%s' failed: %s\n"), optarg, put_rx_errbuf);
				return;
			} else
				put_dir_rx_mask_set = true;
			break;
#endif
		case 'o':
			put_output = tilde_expand_home(optarg, ftp->homedir);
			path_collapse(put_output);
			stripslash(put_output);
			break;
		case 'H':
			opt |= PUT_NOHUP;
			break;
		case 'L':
			free(logfile);
			logfile = xstrdup(optarg);
			unquote(logfile);
			break;
		case 'm': /* --mask */
			free(put_glob_mask);
			put_glob_mask = xstrdup(optarg);
			break;
#ifdef HAVE_REGEX
		case 'M': /* --rx-mask */
			if(put_rx_mask_set) {
				regfree(&put_rx_mask);
				put_rx_mask_set = false;
			}

			ret = regcomp(&put_rx_mask, optarg, REG_EXTENDED);
			if(ret != 0) {
				regerror(ret, &put_rx_mask, put_rx_errbuf, 128);
				ftp_err(_("Regexp '%s' failed: %s\n"), optind, put_rx_errbuf);
				return;
			} else
				put_rx_mask_set = true;
			break;
#endif
		  case 'n':
			opt |= PUT_NEWER;
			break;
		  case 'v':
			opt |= PUT_VERBOSE;
			break;
		  case 'q':
			opt &= ~PUT_VERBOSE;
			break;
		  case 'a':
			opt |= PUT_APPEND;
			break;
		  case 'D':
			opt |= PUT_DELETE_AFTER;
			break;
		  case 'u':
			opt |= PUT_UNIQUE;
			if(!ftp->has_stou_command) {
				fprintf(stderr, _("Remote doesn't support the STOU"
								  " (store unique) command\n"));
				return;
			}
			break;
		  case 'r':
			opt |= PUT_RECURSIVE;
			break;
		  case 's':
			opt |= PUT_SKIP_EXISTING;
			break;
		  case 'R':
			opt |= PUT_RESUME;
			break;
		  case 't':
			opt |= PUT_TAGGED;
			break;
		  case '1':
			if(strncmp(optarg, "ascii", strlen(optarg)) == 0)
				opt |= PUT_ASCII;
			else if(strncmp(optarg, "binary", strlen(optarg)) == 0)
				opt |= PUT_BINARY;
			else {
				printf(_("Invalid option argument --type=%s\n"), optarg);
				return;
			}
			break;
		  case 'p':
			opt |= PUT_PRESERVE;
			break;
		  case 'P':
			opt |= PUT_PARENTS;
			break;
		  case 'h':
			print_put_syntax();;
			return;
		  case '?':
			return;
		}
	}
	if(optind>=argc && !test(opt, PUT_TAGGED)) {
/*		fprintf(stderr, _("missing argument, try 'put --help'"*/
/*						  " for more information\n"));*/
		minargs(optind);
		return;
	}

	if(test(opt, PUT_APPEND) && test(opt, PUT_SKIP_EXISTING)) {
		printf("Can't use --append and --skip-existing simultaneously\n");
		return;
	}

	need_connected();
	need_loggedin();

	gl = lglob_create();
	while(optind < argc) {
		char *f;

		f = tilde_expand_home(argv[optind], gvLocalHomeDir);
		stripslash(f);
		lglob_glob(gl, f, true, put_exclude_func);
		optind++;
	}

	if(list_numitem(gl) == 0) {
		if(!test(opt, PUT_TAGGED)) {
			list_free(gl);
			return;
		} else if(list_numitem(gvLocalTagList) == 0) {
			printf(_("no tagged files\n"));
			list_free(gl);
			return;
		}
	}

	free(ftp->last_mkpath);
	ftp->last_mkpath = 0;

	put_quit = false;
	put_batch = put_owbatch = put_delbatch = test(opt, PUT_FORCE);
	if(test(opt, PUT_FORCE))
		opt &= ~PUT_INTERACTIVE;

	if(put_output && !test(opt, PUT_RECURSIVE) && list_numitem(gl) +
	   (test(opt, PUT_TAGGED) ? list_numitem(gvLocalTagList) : 0) == 1)
		{
			opt |= PUT_OUTPUT_FILE;
		}

	gvInTransfer = true;
	gvInterrupted = false;

	if(test(opt, PUT_NOHUP)) {
		int r = 0;
		pid = fork();

		if(pid == 0) {
			r = transfer_init_nohup(logfile);
			if(r != 0)
				exit(0);
		}

		if(r != 0)
			return;

		if(pid == 0) { /* child process */
			transfer_begin_nohup(argc, argv);

			if(!test(opt, PUT_FORCE) && !test(opt, PUT_RESUME))
				opt |= PUT_UNIQUE;
			opt |= PUT_FORCE;

			putfiles(gl, opt, put_output);
			list_free(gl);
			if(test(opt, PUT_TAGGED)) {
				putfiles(gvLocalTagList, opt, put_output);
				list_clear(gvLocalTagList);
			}
			free(put_output);

			transfer_end_nohup();
		}
		if(pid == -1) {
			perror("fork()");
			return;
		}
		/* parent process */
		sleep(1);
		printf("%d\n", pid);
		input_save_history();
		gvars_destroy();
		reset_xterm_title();
		exit(0);
	}

	putfiles(gl, opt, put_output);
	list_free(gl);
	if(test(opt, PUT_TAGGED)) {
		putfiles(gvLocalTagList, opt, put_output);
		list_clear(gvLocalTagList);
	}
	free(put_output);
	gvInTransfer = false;
}
Esempio n. 2
0
void cmd_get(int argc, char **argv)
{
    list *gl;
    int opt=GET_VERBOSE, c;
    char *logfile = 0;
    pid_t pid;
    struct group *grp;
    char *get_output = 0;
    int stat_thresh = gvStatsThreshold;
#ifdef HAVE_REGEX
    int ret;
    char get_rx_errbuf[129];
#endif
    struct option longopts[] = {
        {"append", no_argument, 0, 'a'},
        {"chmod", required_argument, 0, 'c'},
        {"chgrp", required_argument, 0, '2'},
        {"no-dereference", no_argument, 0, 'd'},
        {"delete-after", no_argument, 0, 'D'},
        {"dir-mask", required_argument, 0, '3'},
#ifdef HAVE_REGEX
        {"dir-rx-mask", required_argument, 0, '4'},
#endif
        {"interactive", no_argument, 0, 'i'},
        {"skip-empty", no_argument, 0, 'e'},
        {"force", no_argument, 0, 'f'},
        {"force-newer", no_argument, 0, 'F'},
        {"logfile", required_argument, 0, 'L'},
        {"mask", required_argument, 0, 'm'},
#ifdef HAVE_REGEX
        {"rx-mask", required_argument, 0, 'M'},
#endif
        {"newer", no_argument, 0, 'n'},
        {"nohup", no_argument, 0, 'H'},
        {"verbose", no_argument, 0, 'v'},
        {"preserve", no_argument, 0, 'p'},
        {"parents", no_argument, 0, 'P'},
        {"quiet", no_argument, 0, 'q'},
        {"recursive", no_argument, 0, 'r'},
        {"resume", no_argument, 0, 'R'},
        {"skip-existing", no_argument, 0, 's'},
        {"stats", optional_argument, 0, 'S'},
        {"tagged", no_argument, 0, 't'},
        {"type", required_argument, 0, '1'},
        {"unique", no_argument, 0, 'u'},
        {"output", required_argument, 0, 'o'},
        {"help", no_argument, 0, 'h'},
        {0, 0, 0, 0},
    };

    if(cmod) {
        mode_free(cmod);
        cmod = 0;
    }

    if(get_glob_mask) {
        free(get_glob_mask);
        get_glob_mask = 0;
    }
    if(get_dir_glob_mask) {
        free(get_dir_glob_mask);
        get_dir_glob_mask = 0;
    }
#ifdef HAVE_REGEX
    if(get_rx_mask_set) {
        regfree(&get_rx_mask);
        get_rx_mask_set = 0;
    }
    if(get_dir_rx_mask_set) {
        regfree(&get_dir_rx_mask);
        get_dir_rx_mask_set = 0;
    }
#endif

    get_skip_empty = false;

    optind = 0; /* force getopt() to re-initialize */
    while((c=getopt_long(argc, argv, "abHc:dDeio:fFL:tnpPvqrRsuT:m:M:",
                         longopts, 0)) != EOF)
    {
        switch(c) {
          case 'a':
            opt |= GET_APPEND;
            break;
          case 'c':
            cmod = mode_compile(optarg, MODE_MASK_ALL);
            if(cmod == NULL) {
                fprintf(stderr, _("Invalid mode for --chmod: %s\n"), optarg);
                return;
            }
            opt |= GET_CHMOD;
            break;
        case '2': /* --chgrp */
            grp = getgrnam(optarg);
            if(grp == 0) {
                fprintf(stderr, _("%s is not a valid group name\n"), optarg);
                return;
            }
            {
                int i;
                for(i=0; grp->gr_mem && grp->gr_mem[i]; i++) {
                    if(strcmp(gvUsername, grp->gr_mem[i]) == 0)
                        break;
                }
                if(!grp->gr_mem[i]) {
                    fprintf(stderr,
                            _("you are not a member of group %s\n"), optarg);
                    return;
                }
            }
            group_change = grp->gr_gid;
            opt |= GET_CHGRP;
            break;
          case 'D':
            opt |= GET_DELETE_AFTER;
            break;
          case 'd':
            opt |= GET_NO_DEREFERENCE;
            break;
           case 'e':
              opt |= GET_SKIP_EMPTY;
              get_skip_empty = true;
              break;
        case '3': /* --dir-mask=GLOB */
            free(get_dir_glob_mask);
            get_dir_glob_mask = xstrdup(optarg);
            unquote(get_dir_glob_mask);
            break;
#ifdef HAVE_REGEX
        case '4': /* --dir-rx-mask=REGEXP */
            if(get_dir_rx_mask_set) {
                regfree(&get_dir_rx_mask);
                get_dir_rx_mask_set = false;
            }
            unquote(optarg);
            ret = regcomp(&get_dir_rx_mask, optarg, REG_EXTENDED);
            if(ret != 0) {
                regerror(ret, &get_dir_rx_mask, get_rx_errbuf, sizeof(get_rx_errbuf) - 1);
                ftp_err(_("Regexp '%s' failed: %s\n"), optarg, get_rx_errbuf);
                return;
            } else
                get_dir_rx_mask_set = true;
            break;
#endif
          case 'i':
            opt |= GET_INTERACTIVE;
            break;
          case 'f':
            opt |= GET_FORCE;
            break;
          case 'F':
            opt |= GET_FORCE_NEWER;
            break;
        case 'm': /* --mask */
            free(get_glob_mask);
            get_glob_mask = xstrdup(optarg);
            unquote(get_glob_mask);
            break;
#ifdef HAVE_REGEX
        case 'M': /* --rx-mask */
            if(get_rx_mask_set) {
                regfree(&get_rx_mask);
                get_rx_mask_set = false;
            }
            unquote(optarg);
            ret = regcomp(&get_rx_mask, optarg, REG_EXTENDED);
            if(ret != 0) {
                regerror(ret, &get_rx_mask, get_rx_errbuf, sizeof(get_rx_errbuf) - 1);
                ftp_err(_("Regexp '%s' failed: %s\n"), optarg, get_rx_errbuf);
                return;
            } else
                get_rx_mask_set = true;
            break;
#endif
          case 'o':
            get_output = tilde_expand_home(optarg, gvLocalHomeDir);
            /*stripslash(get_output);*/
            unquote(get_output);
            break;
          case 'v':
            opt |= GET_VERBOSE;
            break;
          case 'p':
            opt |= GET_PRESERVE;
            break;
          case 'P':
            opt |= GET_PARENTS;
            break;
          case 'H':
            opt |= GET_NOHUP;
            break;
          case 'q':
            opt &= ~GET_VERBOSE;
            break;
          case 'r':
            opt |= GET_RECURSIVE;
            break;
          case 's':
            opt |= GET_SKIP_EXISTING;
            break;
          case 'S':
            stat_thresh = optarg ? atoi(optarg) : 0;
            break;
          case 'R':
            opt |= GET_RESUME;
            break;
          case '1':
            if(strncmp(optarg, "ascii", strlen(optarg)) == 0)
                opt |= GET_ASCII;
            else if(strncmp(optarg, "binary", strlen(optarg)) == 0)
                opt |= GET_BINARY;
            else {
                printf(_("Invalid option argument --type=%s\n"), optarg);
                return;
            }
            break;
          case 'u':
            opt |= GET_UNIQUE;
            break;
          case 'L':
              free(logfile);
              logfile = xstrdup(optarg);
              unquote(logfile);
              break;
          case 't':
            opt |= GET_TAGGED;
            break;
          case 'n':
            opt |= GET_NEWER;
            break;
          case 'h':
            print_get_syntax();
            return;
          case '?':
            return;
        }
    }
    if(optind>=argc && !test(opt, GET_TAGGED)) {
        minargs(optind);
        return;
    }

    need_connected();
    need_loggedin();

    gl = rglob_create();
    while(optind < argc) {
        stripslash(argv[optind]);
        if(rglob_glob(gl, argv[optind], true, true, get_exclude_func) == -1)
            fprintf(stderr, _("%s: no matches found\n"), argv[optind]);
        optind++;
    }
    if(list_numitem(gl) == 0 && !test(opt, GET_TAGGED)) {
        rglob_destroy(gl);
        return;
    }
    if(test(opt, GET_TAGGED)
       && (!ftp->taglist || list_numitem(ftp->taglist)==0))
    {
        printf(_("no tagged files\n"));
        if(list_numitem(gl) == 0) {
            rglob_destroy(gl);
            return;
        }
    }

    get_quit = false;
    get_batch = get_owbatch = get_delbatch = test(opt, GET_FORCE);
    if(test(opt, GET_FORCE))
        opt &= ~GET_INTERACTIVE;

    if(get_output && !test(opt, GET_RECURSIVE) && list_numitem(gl) +
       (test(opt, GET_TAGGED) ? list_numitem(ftp->taglist) : 0) == 1)
        {
            /* if the argument to --output ends with a slash, we assume the
             * user wants the destination to be a directory
             */
            char *e = strrchr(get_output, 0);
            if(e && e[-1] != '/')
                opt |= GET_OUTPUT_FILE;
        }

    stats_reset(gvStatsTransfer);

    gvInTransfer = true;
    gvInterrupted = false;

    if(test(opt, GET_NOHUP)) {
        int r = 0;
        pid = fork();

        if(pid == 0) {
            r = transfer_init_nohup(logfile);
            if(r != 0)
                exit(0);
        }

        if(r != 0)
            return;

        if(pid == 0) { /* child process */
            transfer_begin_nohup(argc, argv);

            if(!test(opt, GET_FORCE) && !test(opt, GET_RESUME))
                opt |= GET_UNIQUE;
            opt |= GET_FORCE;

            if(list_numitem(gl))
                getfiles(gl, opt, get_output);
            rglob_destroy(gl);
            if(ftp->taglist && test(opt, GET_TAGGED))
                getfiles(ftp->taglist, opt, get_output);
            free(get_output);

            transfer_end_nohup();
        }
        if(pid == -1) {
            perror("fork()");
            return;
        }
        /* parent process */
        sleep(1);
        printf("%d\n", pid);
        input_save_history();
        gvars_destroy();
        reset_xterm_title();
        exit(0);
    }

    if(list_numitem(gl))
        getfiles(gl, opt, get_output);
    rglob_destroy(gl);
    if(ftp->taglist && test(opt, GET_TAGGED))
        getfiles(ftp->taglist, opt, get_output);
    free(get_output);
    mode_free(cmod);
    cmod = 0;
    gvInTransfer = false;

    stats_display(gvStatsTransfer, stat_thresh);
}
Esempio n. 3
0
File: fxp.c Progetto: Celelibi/yafc
void cmd_fxp(int argc, char **argv)
{
	list *gl;
	listitem *fxp_tmp = 0;
	char *logfile = 0;
	char *fxp_output = 0;
#ifdef HAVE_REGEX
	int ret;
	char fxp_rx_errbuf[129];
#endif
	int c, opt = FXP_VERBOSE;
	struct option longopts[] = {
		{"append", no_argument, 0, 'a'},
		{"delete-after", no_argument, 0, 'D'},
		{"dir-mask", required_argument, 0, '3'},
#ifdef HAVE_REGEX
		{"dir-rx-mask", required_argument, 0, '4'},
#endif
		{"force", no_argument, 0, 'f'},
    {"force-newer", no_argument, 0, 'F'},
		{"nohup", no_argument, 0, 'H'},
		{"interactive", no_argument, 0, 'i'},
		{"logfile", required_argument, 0, 'L'},
		{"mask", required_argument, 0, 'm'},
#ifdef HAVE_REGEX
		{"rx-mask", required_argument, 0, 'M'},
#endif
		{"newer", no_argument, 0, 'n'},
		{"output", required_argument, 0, 'o'},
		{"preserve", no_argument, 0, 'p'},
		{"parents", no_argument, 0, 'P'},
		{"quiet", no_argument, 0, 'q'},
		{"recursive", no_argument, 0, 'r'},
		{"resume", no_argument, 0, 'R'},
		{"skip-existing", no_argument, 0, 's'},
		{"tagged", no_argument, 0, 't'},
		{"target", required_argument, 0, 'T'},
		{"type", required_argument, 0, '1'},
		{"unique", no_argument, 0, 'u'},
		{"verbose", no_argument, 0, 'v'},
		{"help", no_argument, 0, 'h'},
		{0, 0, 0, 0}
	};

	if(fxp_glob_mask) {
		free(fxp_glob_mask);
		fxp_glob_mask = 0;
	}
	if(fxp_dir_glob_mask) {
		free(fxp_dir_glob_mask);
		fxp_dir_glob_mask = 0;
	}
#ifdef HAVE_REGEX
	if(fxp_rx_mask_set) {
		fxp_rx_mask_set = 0;
	}
	if(fxp_dir_rx_mask_set) {
		regfree(&fxp_dir_rx_mask);
		fxp_dir_rx_mask_set = 0;
	}
#endif

	if(list_numitem(gvFtpList) == 2) {
		fxp_tmp = gvFtpList->first;
		if(fxp_tmp->data == ftp)
			fxp_target = fxp_tmp->next->data;
		else
			fxp_target = fxp_tmp->data;
	} else
		fxp_target = 0;

	fxp_skip_empty = false;

	optind = 0; /* force getopt() to re-initialize */
	while((c=getopt_long(argc, argv, "aDefHiL:M:no:pPqrRstT:uvh",
						 longopts, 0)) != EOF)
		{
			switch(c) {
			case 'a': /* --append */
				opt |= FXP_APPEND;
				break;
			case 'D': /* --delete-after */
				opt |= FXP_DELETE_AFTER;
				break;
			case 'f': /* --force */
				opt |= FXP_FORCE;
				break;
      case 'F':
        opt |= FXP_FORCE_NEWER;
        break;
			   case 'e': /* --skip-empty */
				  opt |= FXP_SKIP_EMPTY;
				  fxp_skip_empty = true;
				  break;
			case '3': /* --dir-mask=GLOB */
				free(fxp_dir_glob_mask);
				fxp_dir_glob_mask = xstrdup(optarg);
				unquote(fxp_dir_glob_mask);
				break;
#ifdef HAVE_REGEX
			case '4': /* --dir-rx-mask=REGEXP */
				if(fxp_dir_rx_mask_set) {
					regfree(&fxp_dir_rx_mask);
					fxp_dir_rx_mask_set = false;
				}
				unquote(optarg);
				ret = regcomp(&fxp_dir_rx_mask, optarg, REG_EXTENDED);
				if(ret != 0) {
					regerror(ret, &fxp_dir_rx_mask, fxp_rx_errbuf, 128);
					ftp_err(_("Regexp '%s' failed: %s\n"),
							optarg, fxp_rx_errbuf);
					return;
				} else
					fxp_dir_rx_mask_set = true;
				break;
#endif
			case 'H': /* --nohup */
				opt |= FXP_NOHUP;
				break;
			case 'i': /* --interactive */
				opt |= FXP_INTERACTIVE;
				break;
			case 'L': /* --logfile=FILE */
				free(logfile);
				logfile = xstrdup(optarg);
				unquote(logfile);
				break;
			case 'm': /* --mask=GLOB */
				free(fxp_glob_mask);
				fxp_glob_mask = xstrdup(optarg);
				unquote(fxp_glob_mask);
				break;
#ifdef HAVE_REGEX
			case 'M': /* --rx-mask=REGEXP */
				if(fxp_rx_mask_set) {
					regfree(&fxp_rx_mask);
					fxp_rx_mask_set = false;
				}

				unquote(optarg);
				ret = regcomp(&fxp_rx_mask, optarg, REG_EXTENDED);
				if(ret != 0) {
					regerror(ret, &fxp_rx_mask, fxp_rx_errbuf, 128);
					ftp_err(_("Regexp '%s' failed: %s\n"),
							optarg, fxp_rx_errbuf);
					return;
				} else
					fxp_rx_mask_set = true;
				break;
#endif
			case 'n': /* --newer */
				opt |= FXP_NEWER;
				break;
			case 'o': /* --output=DIRECTORY */
				if(fxp_target == 0) {
					printf(_("FxP target not set, use --target=NAME"
							 " (as first option)\n"));
					return;
				}
				fxp_output = tilde_expand_home(optarg, fxp_target->homedir);
				stripslash(fxp_output);
				unquote(fxp_output);
				break;
			case 'p': /* --preserve */
				opt |= FXP_PRESERVE;
				break;
			case 'P': /* --parents */
				opt |= FXP_PARENTS;
				break;
			case 'q': /* --quiet */
				opt &= ~FXP_VERBOSE;
				break;
			case 'r': /* --recursive */
				opt |= FXP_RECURSIVE;
				break;
			case 'R': /* --resume */
				opt |= FXP_RESUME;
				break;
			case 's':
				opt |= FXP_SKIP_EXISTING;
				break;
			case 't': /* --tagged */
				opt |= FXP_TAGGED;
				break;
			case '1': /* --type=[ascii|binary] */
				if(strncmp(optarg, "ascii", strlen(optarg)) == 0)
					opt |= FXP_ASCII;
				else if(strncmp(optarg, "binary", strlen(optarg)) == 0)
					opt |= FXP_BINARY;
				else {
					printf(_("Invalid option argument --type=%s\n"), optarg);
					return;
				}
				break;
			case 'T': /* --target=HOST */
				fxp_tmp = ftplist_search(optarg);
				if(!fxp_tmp)
					return;
				fxp_target = (Ftp *)fxp_tmp->data;
				break;
			case 'u': /* --unique */
				opt |= FXP_UNIQUE;
				break;
			case 'v': /* --verbose */
				opt |= FXP_VERBOSE;
				break;
			case 'h': /* --help */
				print_fxp_syntax();
				return;
			case '?':
			default:
				return;
			}
		}

	if(optind >= argc && !test(opt, FXP_TAGGED)) {
		minargs(optind);
		return;
	}

	need_connected();
	need_loggedin();

	if(fxp_target == 0) {
		ftp_err(_("No target specified, try '%s --help'"
				  " for more information\n"), argv[0]);
		return;
	}

#ifdef HAVE_LIBSSH
	if(ftp->session || fxp_target->session) {
		ftp_err("FxP for SSH connections no implemented\n");
		return;
	}
#endif

	gl = rglob_create();
	while(optind < argc) {
		stripslash(argv[optind]);
		if(rglob_glob(gl, argv[optind], true, true, fxp_exclude_func) == -1)
			fprintf(stderr, _("%s: no matches found\n"), argv[optind]);
		optind++;
	}
	if(list_numitem(gl) == 0 && !test(opt, FXP_TAGGED)) {
		rglob_destroy(gl);
		return;
	}
	if(test(opt, FXP_TAGGED)
	   && (!ftp->taglist || list_numitem(ftp->taglist) == 0))
	{
		printf(_("no tagged files\n"));
		if(list_numitem(gl) == 0) {
			rglob_destroy(gl);
			return;
		}
	}

	fxp_quit = false;
	fxp_batch = fxp_owbatch = fxp_delbatch = test(opt, FXP_FORCE);
	if(test(opt, FXP_FORCE))
		opt &= ~FXP_INTERACTIVE;

	if(fxp_output && !test(opt, FXP_RECURSIVE) && list_numitem(gl) +
	   (test(opt, FXP_TAGGED) ? list_numitem(ftp->taglist) : 0) == 1)
		{
			opt |= FXP_OUTPUT_FILE;
		}

	gvInTransfer = true;
	gvInterrupted = false;

	if(test(opt, FXP_NOHUP)) {
		int r = 0;
		pid_t pid = fork();

		if(pid == 0) {
			r = transfer_init_nohup(logfile);
			if(r != 0)
				exit(0);
		}

		if(r != 0)
			return;

		if(pid == 0) { /* child process */
			transfer_begin_nohup(argc, argv);

			if(!test(opt, FXP_FORCE) && !test(opt, FXP_RESUME))
				opt |= FXP_UNIQUE;
			opt |= FXP_FORCE;

			if(list_numitem(gl))
				fxpfiles(gl, opt, fxp_output);
			rglob_destroy(gl);

			if(ftp->taglist && test(opt, FXP_TAGGED))
				fxpfiles(ftp->taglist, opt, fxp_output);

			free(fxp_output);

			transfer_end_nohup();
		}
		if(pid == -1) {
			perror("fork()");
			return;
		}
		/* parent process */
		sleep(1);
		printf("%d\n", pid);
		input_save_history();
		gvars_destroy();
		reset_xterm_title();
		exit(0);
	}

	if(list_numitem(gl))
		fxpfiles(gl, opt, fxp_output);
	rglob_destroy(gl);

	if(ftp->taglist && test(opt, FXP_TAGGED))
		fxpfiles(ftp->taglist, opt, fxp_output);

	free(fxp_output);
	gvInTransfer = false;
}