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

📄 psftp.c

📁 远程登陆工具软件源码 用于远程登陆unix
💻 C
📖 第 1 页 / 共 4 页
字号:
	printf("lcd: unable to change directory: %s\n", errmsg);
	sfree(errmsg);
	return 0;
    }

    currdir = psftp_getcwd();
    printf("New local directory is %s\n", currdir);
    sfree(currdir);

    return 1;
}

static int sftp_cmd_lpwd(struct sftp_command *cmd)
{
    char *currdir;

    currdir = psftp_getcwd();
    printf("Current local directory is %s\n", currdir);
    sfree(currdir);

    return 1;
}

static int sftp_cmd_pling(struct sftp_command *cmd)
{
    int exitcode;

    exitcode = system(cmd->words[1]);
    return (exitcode == 0);
}

static int sftp_cmd_help(struct sftp_command *cmd);

static struct sftp_cmd_lookup {
    char *name;
    /*
     * For help purposes, there are two kinds of command:
     * 
     *  - primary commands, in which `longhelp' is non-NULL. In
     *    this case `shorthelp' is descriptive text, and `longhelp'
     *    is longer descriptive text intended to be printed after
     *    the command name.
     * 
     *  - alias commands, in which `longhelp' is NULL. In this case
     *    `shorthelp' is the name of a primary command, which
     *    contains the help that should double up for this command.
     */
    int listed;			       /* do we list this in primary help? */
    char *shorthelp;
    char *longhelp;
    int (*obey) (struct sftp_command *);
} sftp_lookup[] = {
    /*
     * List of sftp commands. This is binary-searched so it MUST be
     * in ASCII order.
     */
    {
	"!", TRUE, "run a local command",
	    "<command>\n"
	    /* FIXME: this example is crap for non-Windows. */
	    "  Runs a local command. For example, \"!del myfile\".\n",
	    sftp_cmd_pling
    },
    {
	"bye", TRUE, "finish your SFTP session",
	    "\n"
	    "  Terminates your SFTP session and quits the PSFTP program.\n",
	    sftp_cmd_quit
    },
    {
	"cd", TRUE, "change your remote working directory",
	    " [ <New working directory> ]\n"
	    "  Change the remote working directory for your SFTP session.\n"
	    "  If a new working directory is not supplied, you will be\n"
	    "  returned to your home directory.\n",
	    sftp_cmd_cd
    },
    {
	"chmod", TRUE, "change file permissions and modes",
	    " ( <octal-digits> | <modifiers> ) <filename>\n"
	    "  Change the file permissions on a file or directory.\n"
	    "  <octal-digits> can be any octal Unix permission specifier.\n"
	    "  Alternatively, <modifiers> can include:\n"
	    "    u+r     make file readable by owning user\n"
	    "    u+w     make file writable by owning user\n"
	    "    u+x     make file executable by owning user\n"
	    "    u-r     make file not readable by owning user\n"
	    "    [also u-w, u-x]\n"
	    "    g+r     make file readable by members of owning group\n"
	    "    [also g+w, g+x, g-r, g-w, g-x]\n"
	    "    o+r     make file readable by all other users\n"
	    "    [also o+w, o+x, o-r, o-w, o-x]\n"
	    "    a+r     make file readable by absolutely everybody\n"
	    "    [also a+w, a+x, a-r, a-w, a-x]\n"
	    "    u+s     enable the Unix set-user-ID bit\n"
	    "    u-s     disable the Unix set-user-ID bit\n"
	    "    g+s     enable the Unix set-group-ID bit\n"
	    "    g-s     disable the Unix set-group-ID bit\n"
	    "    +t      enable the Unix \"sticky bit\"\n"
	    "  You can give more than one modifier for the same user (\"g-rwx\"), and\n"
	    "  more than one user for the same modifier (\"ug+w\"). You can\n"
	    "  use commas to separate different modifiers (\"u+rwx,g+s\").\n",
	    sftp_cmd_chmod
    },
    {
	"del", TRUE, "delete a file",
	    " <filename>\n"
	    "  Delete a file.\n",
	    sftp_cmd_rm
    },
    {
	"delete", FALSE, "del", NULL, sftp_cmd_rm
    },
    {
	"dir", TRUE, "list contents of a remote directory",
	    " [ <directory-name> ]\n"
	    "  List the contents of a specified directory on the server.\n"
	    "  If <directory-name> is not given, the current working directory\n"
	    "  will be listed.\n",
	    sftp_cmd_ls
    },
    {
	"exit", TRUE, "bye", NULL, sftp_cmd_quit
    },
    {
	"get", TRUE, "download a file from the server to your local machine",
	    " <filename> [ <local-filename> ]\n"
	    "  Downloads a file on the server and stores it locally under\n"
	    "  the same name, or under a different one if you supply the\n"
	    "  argument <local-filename>.\n",
	    sftp_cmd_get
    },
    {
	"help", TRUE, "give help",
	    " [ <command> [ <command> ... ] ]\n"
	    "  Give general help if no commands are specified.\n"
	    "  If one or more commands are specified, give specific help on\n"
	    "  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
    },
    {
	"mkdir", TRUE, "create a directory on the remote server",
	    " <directory-name>\n"
	    "  Creates a directory with the given name on the server.\n",
	    sftp_cmd_mkdir
    },
    {
	"mv", TRUE, "move or rename a file on the remote server",
	    " <source-filename> <destination-filename>\n"
	    "  Moves or renames the file <source-filename> on the server,\n"
	    "  so that it is accessible under the name <destination-filename>.\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 did not already specify a host name on the command\n"
	    "  line.\n",
	    sftp_cmd_open
    },
    {
	"put", TRUE, "upload a file from your local machine to the server",
	    " <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",
	    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 a file",
	    " <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",
	    sftp_cmd_reget
    },
    {
	"ren", TRUE, "mv", NULL,
	    sftp_cmd_mv
    },
    {
	"rename", FALSE, "mv", NULL,
	    sftp_cmd_mv
    },
    {
	"reput", TRUE, "continue uploading a file",
	    " <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",
	    sftp_cmd_reput
    },
    {
	"rm", TRUE, "del", NULL,
	    sftp_cmd_rm
    },
    {
	"rmdir", TRUE, "remove a directory on the remote server",
	    " <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",
	    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;
    int linelen, linesize;
    struct sftp_command *cmd;
    char *p, *q, *r;
    int quoting;

    if ((mode == 0) || (modeflags & 1)) {
	printf("psftp> ");
    }
    fflush(stdout);

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

    line = NULL;
    linesize = linelen = 0;
    while (1) {
	int len;
	char *ret;

	linesize += 512;
	line = sresize(line, linesize, char);
	ret = fgets(line + linelen, linesize - linelen, fp);

	if (!ret || (linelen == 0 && line[0] == '\0')) {
	    cmd->obey = sftp_cmd_quit;
	    if ((mode == 0) || (modeflags & 1))
		printf("quit\n");
	    return cmd;		       /* eof */
	}
	len = linelen + strlen(line + linelen);
	linelen += len;
	if (line[linelen - 1] == '\n') {
	    linelen--;
	    line[linelen] = '\0';
	    break;
	}
    }
    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();
    }
    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(stdin, 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;

⌨️ 快捷键说明

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