⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 psftp.c

📁 putty
💻 C
📖 第 1 页 / 共 5 页
字号:
	    "  those particular commands.\n",
	    sftp_cmd_help
    },
    {
	"lcd", TRUE, "change local working directory",
	    " <local-directory-name>\n"
	    "  Change the local working directory of the PSFTP program (the\n"
	    "  default location where the \"get\" command will save files).\n",
	    sftp_cmd_lcd
    },
    {
	"lpwd", TRUE, "print local working directory",
	    "\n"
	    "  Print the local working directory of the PSFTP program (the\n"
	    "  default location where the \"get\" command will save files).\n",
	    sftp_cmd_lpwd
    },
    {
	"ls", TRUE, "dir", NULL,
	    sftp_cmd_ls
    },
    {
	"mget", TRUE, "download multiple files at once",
	    " [ -r ] [ -- ] <filename-or-wildcard> [ <filename-or-wildcard>... ]\n"
	    "  Downloads many files from the server, storing each one under\n"
	    "  the same name it has on the server side. You can use wildcards\n"
	    "  such as \"*.c\" to specify lots of files at once.\n"
	    "  If -r specified, recursively fetch files and directories.\n",
	    sftp_cmd_mget
    },
    {
	"mkdir", TRUE, "create directories on the remote server",
	    " <directory-name> [ <directory-name>... ]\n"
	    "  Creates directories with the given names on the server.\n",
	    sftp_cmd_mkdir
    },
    {
	"mput", TRUE, "upload multiple files at once",
	    " [ -r ] [ -- ] <filename-or-wildcard> [ <filename-or-wildcard>... ]\n"
	    "  Uploads many files to the server, storing each one under the\n"
	    "  same name it has on the client side. You can use wildcards\n"
	    "  such as \"*.c\" to specify lots of files at once.\n"
	    "  If -r specified, recursively store files and directories.\n",
	    sftp_cmd_mput
    },
    {
	"mv", TRUE, "move or rename file(s) on the remote server",
	    " <source> [ <source>... ] <destination>\n"
	    "  Moves or renames <source>(s) on the server to <destination>,\n"
	    "  also on the server.\n"
	    "  If <destination> specifies an existing directory, then <source>\n"
	    "  may be a wildcard, and multiple <source>s may be given; all\n"
	    "  source files are moved into <destination>.\n"
	    "  Otherwise, <source> must specify a single file, which is moved\n"
	    "  or renamed so that it is accessible under the name <destination>.\n",
	    sftp_cmd_mv
    },
    {
	"open", TRUE, "connect to a host",
	    " [<user>@]<hostname> [<port>]\n"
	    "  Establishes an SFTP connection to a given host. Only usable\n"
	    "  when you are not already connected to a server.\n",
	    sftp_cmd_open
    },
    {
	"put", TRUE, "upload a file from your local machine to the server",
	    " [ -r ] [ -- ] <filename> [ <remote-filename> ]\n"
	    "  Uploads a file to the server and stores it there under\n"
	    "  the same name, or under a different one if you supply the\n"
	    "  argument <remote-filename>.\n"
	    "  If -r specified, recursively store a directory.\n",
	    sftp_cmd_put
    },
    {
	"pwd", TRUE, "print your remote working directory",
	    "\n"
	    "  Print the current remote working directory for your SFTP session.\n",
	    sftp_cmd_pwd
    },
    {
	"quit", TRUE, "bye", NULL,
	    sftp_cmd_quit
    },
    {
	"reget", TRUE, "continue downloading files",
	    " [ -r ] [ -- ] <filename> [ <local-filename> ]\n"
	    "  Works exactly like the \"get\" command, but the local file\n"
	    "  must already exist. The download will begin at the end of the\n"
	    "  file. This is for resuming a download that was interrupted.\n"
	    "  If -r specified, resume interrupted \"get -r\".\n",
	    sftp_cmd_reget
    },
    {
	"ren", TRUE, "mv", NULL,
	    sftp_cmd_mv
    },
    {
	"rename", FALSE, "mv", NULL,
	    sftp_cmd_mv
    },
    {
	"reput", TRUE, "continue uploading files",
	    " [ -r ] [ -- ] <filename> [ <remote-filename> ]\n"
	    "  Works exactly like the \"put\" command, but the remote file\n"
	    "  must already exist. The upload will begin at the end of the\n"
	    "  file. This is for resuming an upload that was interrupted.\n"
	    "  If -r specified, resume interrupted \"put -r\".\n",
	    sftp_cmd_reput
    },
    {
	"rm", TRUE, "del", NULL,
	    sftp_cmd_rm
    },
    {
	"rmdir", TRUE, "remove directories on the remote server",
	    " <directory-name> [ <directory-name>... ]\n"
	    "  Removes the directory with the given name on the server.\n"
	    "  The directory will not be removed unless it is empty.\n"
	    "  Wildcards may be used to specify multiple directories.\n",
	    sftp_cmd_rmdir
    }
};

const struct sftp_cmd_lookup *lookup_command(char *name)
{
    int i, j, k, cmp;

    i = -1;
    j = sizeof(sftp_lookup) / sizeof(*sftp_lookup);
    while (j - i > 1) {
	k = (j + i) / 2;
	cmp = strcmp(name, sftp_lookup[k].name);
	if (cmp < 0)
	    j = k;
	else if (cmp > 0)
	    i = k;
	else {
	    return &sftp_lookup[k];
	}
    }
    return NULL;
}

static int sftp_cmd_help(struct sftp_command *cmd)
{
    int i;
    if (cmd->nwords == 1) {
	/*
	 * Give short help on each command.
	 */
	int maxlen;
	maxlen = 0;
	for (i = 0; i < sizeof(sftp_lookup) / sizeof(*sftp_lookup); i++) {
	    int len;
	    if (!sftp_lookup[i].listed)
		continue;
	    len = strlen(sftp_lookup[i].name);
	    if (maxlen < len)
		maxlen = len;
	}
	for (i = 0; i < sizeof(sftp_lookup) / sizeof(*sftp_lookup); i++) {
	    const struct sftp_cmd_lookup *lookup;
	    if (!sftp_lookup[i].listed)
		continue;
	    lookup = &sftp_lookup[i];
	    printf("%-*s", maxlen+2, lookup->name);
	    if (lookup->longhelp == NULL)
		lookup = lookup_command(lookup->shorthelp);
	    printf("%s\n", lookup->shorthelp);
	}
    } else {
	/*
	 * Give long help on specific commands.
	 */
	for (i = 1; i < cmd->nwords; i++) {
	    const struct sftp_cmd_lookup *lookup;
	    lookup = lookup_command(cmd->words[i]);
	    if (!lookup) {
		printf("help: %s: command not found\n", cmd->words[i]);
	    } else {
		printf("%s", lookup->name);
		if (lookup->longhelp == NULL)
		    lookup = lookup_command(lookup->shorthelp);
		printf("%s", lookup->longhelp);
	    }
	}
    }
    return 1;
}

/* ----------------------------------------------------------------------
 * Command line reading and parsing.
 */
struct sftp_command *sftp_getcmd(FILE *fp, int mode, int modeflags)
{
    char *line;
    struct sftp_command *cmd;
    char *p, *q, *r;
    int quoting;

    cmd = snew(struct sftp_command);
    cmd->words = NULL;
    cmd->nwords = 0;
    cmd->wordssize = 0;

    line = NULL;

    if (fp) {
	if (modeflags & 1)
	    printf("psftp> ");
	line = fgetline(fp);
    } else {
	line = ssh_sftp_get_cmdline("psftp> ", back == NULL);
    }

    if (!line || !*line) {
	cmd->obey = sftp_cmd_quit;
	if ((mode == 0) || (modeflags & 1))
	    printf("quit\n");
	return cmd;		       /* eof */
    }

    line[strcspn(line, "\r\n")] = '\0';

    if (modeflags & 1) {
	printf("%s\n", line);
    }

    p = line;
    while (*p && (*p == ' ' || *p == '\t'))
	p++;

    if (*p == '!') {
	/*
	 * Special case: the ! command. This is always parsed as
	 * exactly two words: one containing the !, and the second
	 * containing everything else on the line.
	 */
	cmd->nwords = cmd->wordssize = 2;
	cmd->words = sresize(cmd->words, cmd->wordssize, char *);
	cmd->words[0] = dupstr("!");
	cmd->words[1] = dupstr(p+1);
    } else {

	/*
	 * Parse the command line into words. The syntax is:
	 *  - double quotes are removed, but cause spaces within to be
	 *    treated as non-separating.
	 *  - a double-doublequote pair is a literal double quote, inside
	 *    _or_ outside quotes. Like this:
	 *
	 *      firstword "second word" "this has ""quotes"" in" and""this""
	 *
	 * becomes
	 *
	 *      >firstword<
	 *      >second word<
	 *      >this has "quotes" in<
	 *      >and"this"<
	 */
	while (*p) {
	    /* skip whitespace */
	    while (*p && (*p == ' ' || *p == '\t'))
		p++;
	    /* mark start of word */
	    q = r = p;		       /* q sits at start, r writes word */
	    quoting = 0;
	    while (*p) {
		if (!quoting && (*p == ' ' || *p == '\t'))
		    break;		       /* reached end of word */
		else if (*p == '"' && p[1] == '"')
		    p += 2, *r++ = '"';    /* a literal quote */
		else if (*p == '"')
		    p++, quoting = !quoting;
		else
		    *r++ = *p++;
	    }
	    if (*p)
		p++;		       /* skip over the whitespace */
	    *r = '\0';
	    if (cmd->nwords >= cmd->wordssize) {
		cmd->wordssize = cmd->nwords + 16;
		cmd->words = sresize(cmd->words, cmd->wordssize, char *);
	    }
	    cmd->words[cmd->nwords++] = dupstr(q);
	}
    }

    sfree(line);

    /*
     * Now parse the first word and assign a function.
     */

    if (cmd->nwords == 0)
	cmd->obey = sftp_cmd_null;
    else {
	const struct sftp_cmd_lookup *lookup;
	lookup = lookup_command(cmd->words[0]);
	if (!lookup)
	    cmd->obey = sftp_cmd_unknown;
	else
	    cmd->obey = lookup->obey;
    }

    return cmd;
}

static int do_sftp_init(void)
{
    struct sftp_packet *pktin;
    struct sftp_request *req, *rreq;

    /*
     * Do protocol initialisation. 
     */
    if (!fxp_init()) {
	fprintf(stderr,
		"Fatal: unable to initialise SFTP: %s\n", fxp_error());
	return 1;		       /* failure */
    }

    /*
     * Find out where our home directory is.
     */
    sftp_register(req = fxp_realpath_send("."));
    rreq = sftp_find_request(pktin = sftp_recv());
    assert(rreq == req);
    homedir = fxp_realpath_recv(pktin, rreq);

    if (!homedir) {
	fprintf(stderr,
		"Warning: failed to resolve home directory: %s\n",
		fxp_error());
	homedir = dupstr(".");
    } else {
	printf("Remote working directory is %s\n", homedir);
    }
    pwd = dupstr(homedir);
    return 0;
}

void do_sftp_cleanup()
{
    char ch;
    if (back) {
	back->special(backhandle, TS_EOF);
	sftp_recvdata(&ch, 1);
	back->free(backhandle);
	sftp_cleanup_request();
	back = NULL;
	backhandle = NULL;
    }
    if (pwd) {
	sfree(pwd);
	pwd = NULL;
    }
    if (homedir) {
	sfree(homedir);
	homedir = NULL;
    }
}

void do_sftp(int mode, int modeflags, char *batchfile)
{
    FILE *fp;
    int ret;

    /*
     * Batch mode?
     */
    if (mode == 0) {

        /* ------------------------------------------------------------------
         * Now we're ready to do Real Stuff.
         */
        while (1) {
	    struct sftp_command *cmd;
	    cmd = sftp_getcmd(NULL, 0, 0);
	    if (!cmd)
		break;
	    ret = cmd->obey(cmd);
	    if (cmd->words) {
		int i;
		for(i = 0; i < cmd->nwords; i++)
		    sfree(cmd->words[i]);
		sfree(cmd->words);
	    }
	    sfree(cmd);
	    if (ret < 0)
		break;
	}
    } else {
        fp = fopen(batchfile, "r");
        if (!fp) {
	    printf("Fatal: unable to open %s\n", batchfile);
	    return;
        }
        while (1) {
	    struct sftp_command *cmd;
	    cmd = sftp_getcmd(fp, mode, modeflags);
	    if (!cmd)
		break;
	    ret = cmd->obey(cmd);
	    if (ret < 0)
		break;
	    if (ret == 0) {
		if (!(modeflags & 2))
		    break;
	    }
        }
	fclose(fp);

    }
}

/* ----------------------------------------------------------------------
 * Dirty bits: integration with PuTTY.
 */

static int verbose = 0;

/*
 *  Print an error message and perform a fatal exit.
 */
void fatalbox(char *fmt, ...)
{
    char *str, *str2;
    va_list ap;
    va_start(ap, fmt);
    str = dupvprintf(fmt, ap);
    str2 = dupcat("Fatal: ", str, "\n", NULL);
    sfree(str);
    va_end(ap);
    fputs(str2, stderr);
    sfree(str2);

    cleanup_exit(1);
}
void modalfatalbox(char *fmt, ...)
{
    char *str, *str2;
    va_list ap;
    va_start(ap, fmt);
    str = dupvprintf(fmt, ap);
    str2 = dupcat("Fatal: ", str, "\n", NULL);
    sfree(str);
    va_end(ap);
    fputs(str2, stderr);
    sfree(str2);

    cleanup_exit(1);
}
void connection_fatal(void *frontend, char *fmt, ...)
{
    char *str, *str2;
    va_list ap;
    va_start(ap, fmt);
    str = dupvprintf(fmt, ap);
    str2 = dupcat("Fatal: ", str, "\n", NULL);
    sfree(str);
    va_end(ap);
    fputs(str2, stderr);
    sfree(str2);

    cleanup_exit(1);
}

void ldisc_send(void *handle, char *buf, int len, int interactive)
{
    /*
     * This is only here because of the calls to ldisc_send(NULL,
     * 0) in ssh.c. Nothing in PSFTP actually needs to use the
     * ldisc as an ldisc. So if we get called with any real data, I
     * want to know about it.
     */
    assert(len == 0);
}

/*
 * In psftp, all agent requests should be synchronous, so this is a
 * never-called stub.
 */
void agent_schedule_callback(void (*callback)(void *, void *, int),
			     void *callback_ctx, void *data, int len)
{
    assert(!"We shouldn't be here");
}

/*
 * Receive a block of data from the SSH link. Block until all data
 * is available.
 *
 * To do this, we repeatedly call the SSH protocol module, with our
 * own tr

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -