svnno****@sourc*****
svnno****@sourc*****
2012年 10月 14日 (日) 01:18:30 JST
Revision: 5039 http://sourceforge.jp/projects/ttssh2/scm/svn/commits/5039 Author: yutakapon Date: 2012-10-14 01:18:29 +0900 (Sun, 14 Oct 2012) Log Message: ----------- SSH2遅延送信の不具合で、SSHデータが壊れる問題を修正した。 Modified Paths: -------------- trunk/doc/en/html/about/history.html trunk/doc/ja/html/about/history.html trunk/ttssh2/ttxssh/fwd.c trunk/ttssh2/ttxssh/sftp.c trunk/ttssh2/ttxssh/ssh.c trunk/ttssh2/ttxssh/ssh.h -------------- next part -------------- Modified: trunk/doc/en/html/about/history.html =================================================================== --- trunk/doc/en/html/about/history.html 2012-10-13 15:37:56 UTC (rev 5038) +++ trunk/doc/en/html/about/history.html 2012-10-13 16:18:29 UTC (rev 5039) @@ -1959,6 +1959,7 @@ <li>Bug fixes <ul> <li>SCP sending will be failed for Dropbear 2012.55(SSH server).</li> + <li>The SSH data will be corrupted by SSH2 delay re-transmit bug.</li> </ul> </li> Modified: trunk/doc/ja/html/about/history.html =================================================================== --- trunk/doc/ja/html/about/history.html 2012-10-13 15:37:56 UTC (rev 5038) +++ trunk/doc/ja/html/about/history.html 2012-10-13 16:18:29 UTC (rev 5039) @@ -1960,6 +1960,7 @@ <li>\x83o\x83O\x8FC\x90\xB3 <ul> <li>Dropbear 2012.55(SSH\x83T\x81[\x83o)\x82ɑ\xB5\x82āASCP\x91\x97\x90M\x82\xAA\x8E\xB8\x94s\x82\xB7\x82\xE9\x96\xE2\x91\xE8\x82\xF0\x8FC\x90\xB3\x82\xB5\x82\xBD\x81B</li> + <li>SSH2\x92x\x89\x84\x91\x97\x90M\x82̕s\x8B\x82ŁASSH\x83f\x81[\x83^\x82\xAA\x89\xF3\x82\xEA\x82\xE9\x96\xE2\x91\xE8\x82\xF0\x8FC\x90\xB3\x82\xB5\x82\xBD\x81B</li> </ul> </li> Modified: trunk/ttssh2/ttxssh/fwd.c =================================================================== --- trunk/ttssh2/ttxssh/fwd.c 2012-10-13 15:37:56 UTC (rev 5038) +++ trunk/ttssh2/ttxssh/fwd.c 2012-10-13 16:18:29 UTC (rev 5039) @@ -769,7 +769,7 @@ && (channel->status & FWD_CLOSED_REMOTE_OUT) == 0) { // \x83|\x81[\x83g\x83t\x83H\x83\x8F\x81[\x83f\x83B\x83\x93\x83O\x82ɂ\xA8\x82\xA2\x82ăN\x83\x89\x83C\x83A\x83\x93\x83g\x82\xA9\x82\xE7\x82̑\x97\x90M\x97v\x8B\x81\x82\xF0\x81ASSH\x92ʐM\x82ɏ悹\x82ăT\x81[\x83o\x82܂ő\x97\x82\xE8\x93͂\xAF\x82\xE9\x81B SSH_channel_send(pvar, channel_num, channel->remote_num, new_buf, - amount); + amount, 0); } switch (action) { Modified: trunk/ttssh2/ttxssh/sftp.c =================================================================== --- trunk/ttssh2/ttxssh/sftp.c 2012-10-13 15:37:56 UTC (rev 5038) +++ trunk/ttssh2/ttxssh/sftp.c 2012-10-13 16:18:29 UTC (rev 5039) @@ -216,7 +216,7 @@ // \x8Dŏ\x89\x82Ƀ\x81\x83b\x83Z\x81[\x83W\x83T\x83C\x83Y\x82\xF0\x8Ai\x94[\x82\xB7\x82\xE9\x81B set_uint32(p, len - 4); // \x83y\x83C\x83\x8D\x81[\x83h\x82̑\x97\x90M\x81B - SSH2_send_channel_data(pvar, c, p, len); + SSH2_send_channel_data(pvar, c, p, len, 0); } // \x83T\x81[\x83o\x82\xA9\x82\xE7\x8E\xF3\x90M\x82\xB5\x82\xBDSFTP\x83p\x83P\x83b\x83g\x82\xF0\x83o\x83b\x83t\x83@\x82Ɋi\x94[\x82\xB7\x82\xE9\x81B @@ -433,204 +433,204 @@ return conn->version; } -static void -help(void) -{ - sftp_console_message(g_pvar, g_channel, - "Available commands:\r\n" - "bye Quit sftp\r\n" - "cd path Change remote directory to 'path'\r\n" - "chgrp grp path Change group of file 'path' to 'grp'\r\n" - "chmod mode path Change permissions of file 'path' to 'mode'\r\n" - "chown own path Change owner of file 'path' to 'own'\r\n" - "df [-hi] [path] Display statistics for current directory or\r\n" - " filesystem containing 'path'\r\n" - "exit Quit sftp\r\n" - "get [-Ppr] remote [local] Download file\r\n" - "help Display this help text\r\n" - "lcd path Change local directory to 'path'\r\n" - "lls [ls-options [path]] Display local directory listing\r\n" - "lmkdir path Create local directory\r\n" - "ln [-s] oldpath newpath Link remote file (-s for symlink)\r\n" - "lpwd Print local working directory\r\n" - "ls [-1afhlnrSt] [path] Display remote directory listing\r\n" - "lumask umask Set local umask to 'umask'\r\n" - "mkdir path Create remote directory\r\n" - "progress Toggle display of progress meter\r\n" - "put [-Ppr] local [remote] Upload file\r\n" - "pwd Display remote working directory\r\n" - "quit Quit sftp\r\n" - "rename oldpath newpath Rename remote file\r\n" - "rm path Delete remote file\r\n" - "rmdir path Remove remote directory\r\n" - "symlink oldpath newpath Symlink remote file\r\n" - "version Show SFTP version\r\n" - "!command Execute 'command' in local shell\r\n" - "! Escape to local shell\r\n" - "? Synonym for help\r\n"); -} +static void +help(void) +{ + sftp_console_message(g_pvar, g_channel, + "Available commands:\r\n" + "bye Quit sftp\r\n" + "cd path Change remote directory to 'path'\r\n" + "chgrp grp path Change group of file 'path' to 'grp'\r\n" + "chmod mode path Change permissions of file 'path' to 'mode'\r\n" + "chown own path Change owner of file 'path' to 'own'\r\n" + "df [-hi] [path] Display statistics for current directory or\r\n" + " filesystem containing 'path'\r\n" + "exit Quit sftp\r\n" + "get [-Ppr] remote [local] Download file\r\n" + "help Display this help text\r\n" + "lcd path Change local directory to 'path'\r\n" + "lls [ls-options [path]] Display local directory listing\r\n" + "lmkdir path Create local directory\r\n" + "ln [-s] oldpath newpath Link remote file (-s for symlink)\r\n" + "lpwd Print local working directory\r\n" + "ls [-1afhlnrSt] [path] Display remote directory listing\r\n" + "lumask umask Set local umask to 'umask'\r\n" + "mkdir path Create remote directory\r\n" + "progress Toggle display of progress meter\r\n" + "put [-Ppr] local [remote] Upload file\r\n" + "pwd Display remote working directory\r\n" + "quit Quit sftp\r\n" + "rename oldpath newpath Rename remote file\r\n" + "rm path Delete remote file\r\n" + "rmdir path Remove remote directory\r\n" + "symlink oldpath newpath Symlink remote file\r\n" + "version Show SFTP version\r\n" + "!command Execute 'command' in local shell\r\n" + "! Escape to local shell\r\n" + "? Synonym for help\r\n"); +} -/* - * Split a string into an argument vector using sh(1)-style quoting, - * comment and escaping rules, but with some tweaks to handle glob(3) - * wildcards. - * The "sloppy" flag allows for recovery from missing terminating quote, for - * use in parsing incomplete commandlines during tab autocompletion. - * - * Returns NULL on error or a NULL-terminated array of arguments. - * - * If "lastquote" is not NULL, the quoting character used for the last - * argument is placed in *lastquote ("\0", "'" or "\""). - * - * If "terminated" is not NULL, *terminated will be set to 1 when the - * last argument's quote has been properly terminated or 0 otherwise. - * This parameter is only of use if "sloppy" is set. - */ -#define MAXARGS 128 -#define MAXARGLEN 8192 -static char ** -makeargv(const char *arg, int *argcp, int sloppy, char *lastquote, - u_int *terminated) -{ - int argc, quot; - size_t i, j; - static char argvs[MAXARGLEN]; - static char *argv[MAXARGS + 1]; - enum { MA_START, MA_SQUOTE, MA_DQUOTE, MA_UNQUOTED } state, q; - - *argcp = argc = 0; - if (strlen(arg) > sizeof(argvs) - 1) { - args_too_longs: - sftp_syslog(g_pvar, "string too long"); - return NULL; - } - if (terminated != NULL) - *terminated = 1; - if (lastquote != NULL) - *lastquote = '\0'; - state = MA_START; - i = j = 0; - for (;;) { - if (isspace(arg[i])) { - if (state == MA_UNQUOTED) { - /* Terminate current argument */ - argvs[j++] = '\0'; - argc++; - state = MA_START; - } else if (state != MA_START) - argvs[j++] = arg[i]; - } else if (arg[i] == '"' || arg[i] == '\'') { - q = arg[i] == '"' ? MA_DQUOTE : MA_SQUOTE; - if (state == MA_START) { - argv[argc] = argvs + j; - state = q; - if (lastquote != NULL) - *lastquote = arg[i]; - } else if (state == MA_UNQUOTED) - state = q; - else if (state == q) - state = MA_UNQUOTED; - else - argvs[j++] = arg[i]; - } else if (arg[i] == '\\') { - if (state == MA_SQUOTE || state == MA_DQUOTE) { - quot = state == MA_SQUOTE ? '\'' : '"'; - /* Unescape quote we are in */ - /* XXX support \n and friends? */ - if (arg[i + 1] == quot) { - i++; - argvs[j++] = arg[i]; - } else if (arg[i + 1] == '?' || - arg[i + 1] == '[' || arg[i + 1] == '*') { - /* - * Special case for sftp: append - * double-escaped glob sequence - - * glob will undo one level of - * escaping. NB. string can grow here. - */ - if (j >= sizeof(argvs) - 5) - goto args_too_longs; - argvs[j++] = '\\'; - argvs[j++] = arg[i++]; - argvs[j++] = '\\'; - argvs[j++] = arg[i]; - } else { - argvs[j++] = arg[i++]; - argvs[j++] = arg[i]; - } - } else { - if (state == MA_START) { - argv[argc] = argvs + j; - state = MA_UNQUOTED; - if (lastquote != NULL) - *lastquote = '\0'; - } - if (arg[i + 1] == '?' || arg[i + 1] == '[' || - arg[i + 1] == '*' || arg[i + 1] == '\\') { - /* - * Special case for sftp: append - * escaped glob sequence - - * glob will undo one level of - * escaping. - */ - argvs[j++] = arg[i++]; - argvs[j++] = arg[i]; - } else { - /* Unescape everything */ - /* XXX support \n and friends? */ - i++; - argvs[j++] = arg[i]; - } - } - } else if (arg[i] == '#') { - if (state == MA_SQUOTE || state == MA_DQUOTE) - argvs[j++] = arg[i]; - else - goto string_done; - } else if (arg[i] == '\0') { - if (state == MA_SQUOTE || state == MA_DQUOTE) { - if (sloppy) { - state = MA_UNQUOTED; - if (terminated != NULL) - *terminated = 0; - goto string_done; - } - sftp_syslog(g_pvar, "Unterminated quoted argument"); - return NULL; - } - string_done: - if (state == MA_UNQUOTED) { - argvs[j++] = '\0'; - argc++; - } - break; - } else { - if (state == MA_START) { - argv[argc] = argvs + j; - state = MA_UNQUOTED; - if (lastquote != NULL) - *lastquote = '\0'; - } - if ((state == MA_SQUOTE || state == MA_DQUOTE) && - (arg[i] == '?' || arg[i] == '[' || arg[i] == '*')) { - /* - * Special case for sftp: escape quoted - * glob(3) wildcards. NB. string can grow - * here. - */ - if (j >= sizeof(argvs) - 3) - goto args_too_longs; - argvs[j++] = '\\'; - argvs[j++] = arg[i]; - } else - argvs[j++] = arg[i]; - } - i++; - } - *argcp = argc; - return argv; -} +/* + * Split a string into an argument vector using sh(1)-style quoting, + * comment and escaping rules, but with some tweaks to handle glob(3) + * wildcards. + * The "sloppy" flag allows for recovery from missing terminating quote, for + * use in parsing incomplete commandlines during tab autocompletion. + * + * Returns NULL on error or a NULL-terminated array of arguments. + * + * If "lastquote" is not NULL, the quoting character used for the last + * argument is placed in *lastquote ("\0", "'" or "\""). + * + * If "terminated" is not NULL, *terminated will be set to 1 when the + * last argument's quote has been properly terminated or 0 otherwise. + * This parameter is only of use if "sloppy" is set. + */ +#define MAXARGS 128 +#define MAXARGLEN 8192 +static char ** +makeargv(const char *arg, int *argcp, int sloppy, char *lastquote, + u_int *terminated) +{ + int argc, quot; + size_t i, j; + static char argvs[MAXARGLEN]; + static char *argv[MAXARGS + 1]; + enum { MA_START, MA_SQUOTE, MA_DQUOTE, MA_UNQUOTED } state, q; + *argcp = argc = 0; + if (strlen(arg) > sizeof(argvs) - 1) { + args_too_longs: + sftp_syslog(g_pvar, "string too long"); + return NULL; + } + if (terminated != NULL) + *terminated = 1; + if (lastquote != NULL) + *lastquote = '\0'; + state = MA_START; + i = j = 0; + for (;;) { + if (isspace(arg[i])) { + if (state == MA_UNQUOTED) { + /* Terminate current argument */ + argvs[j++] = '\0'; + argc++; + state = MA_START; + } else if (state != MA_START) + argvs[j++] = arg[i]; + } else if (arg[i] == '"' || arg[i] == '\'') { + q = arg[i] == '"' ? MA_DQUOTE : MA_SQUOTE; + if (state == MA_START) { + argv[argc] = argvs + j; + state = q; + if (lastquote != NULL) + *lastquote = arg[i]; + } else if (state == MA_UNQUOTED) + state = q; + else if (state == q) + state = MA_UNQUOTED; + else + argvs[j++] = arg[i]; + } else if (arg[i] == '\\') { + if (state == MA_SQUOTE || state == MA_DQUOTE) { + quot = state == MA_SQUOTE ? '\'' : '"'; + /* Unescape quote we are in */ + /* XXX support \n and friends? */ + if (arg[i + 1] == quot) { + i++; + argvs[j++] = arg[i]; + } else if (arg[i + 1] == '?' || + arg[i + 1] == '[' || arg[i + 1] == '*') { + /* + * Special case for sftp: append + * double-escaped glob sequence - + * glob will undo one level of + * escaping. NB. string can grow here. + */ + if (j >= sizeof(argvs) - 5) + goto args_too_longs; + argvs[j++] = '\\'; + argvs[j++] = arg[i++]; + argvs[j++] = '\\'; + argvs[j++] = arg[i]; + } else { + argvs[j++] = arg[i++]; + argvs[j++] = arg[i]; + } + } else { + if (state == MA_START) { + argv[argc] = argvs + j; + state = MA_UNQUOTED; + if (lastquote != NULL) + *lastquote = '\0'; + } + if (arg[i + 1] == '?' || arg[i + 1] == '[' || + arg[i + 1] == '*' || arg[i + 1] == '\\') { + /* + * Special case for sftp: append + * escaped glob sequence - + * glob will undo one level of + * escaping. + */ + argvs[j++] = arg[i++]; + argvs[j++] = arg[i]; + } else { + /* Unescape everything */ + /* XXX support \n and friends? */ + i++; + argvs[j++] = arg[i]; + } + } + } else if (arg[i] == '#') { + if (state == MA_SQUOTE || state == MA_DQUOTE) + argvs[j++] = arg[i]; + else + goto string_done; + } else if (arg[i] == '\0') { + if (state == MA_SQUOTE || state == MA_DQUOTE) { + if (sloppy) { + state = MA_UNQUOTED; + if (terminated != NULL) + *terminated = 0; + goto string_done; + } + sftp_syslog(g_pvar, "Unterminated quoted argument"); + return NULL; + } + string_done: + if (state == MA_UNQUOTED) { + argvs[j++] = '\0'; + argc++; + } + break; + } else { + if (state == MA_START) { + argv[argc] = argvs + j; + state = MA_UNQUOTED; + if (lastquote != NULL) + *lastquote = '\0'; + } + if ((state == MA_SQUOTE || state == MA_DQUOTE) && + (arg[i] == '?' || arg[i] == '[' || arg[i] == '*')) { + /* + * Special case for sftp: escape quoted + * glob(3) wildcards. NB. string can grow + * here. + */ + if (j >= sizeof(argvs) - 3) + goto args_too_longs; + argvs[j++] = '\\'; + argvs[j++] = arg[i]; + } else + argvs[j++] = arg[i]; + } + i++; + } + *argcp = argc; + return argv; +} + static int parse_args(const char **cpp, int *pflag, int *rflag, int *lflag, int *iflag, int *hflag, int *sflag, unsigned long *n_arg, char **path1, char **path2) { @@ -658,150 +658,150 @@ if ((argv = makeargv(cp, &argc, 0, NULL, NULL)) == NULL) return -1; - /* Figure out which command we have */ - for (i = 0; cmds[i].c != NULL; i++) { - if (_strcmpi(cmds[i].c, argv[0]) == 0) - break; - } - cmdnum = cmds[i].n; - cmd = cmds[i].c; - - /* Special case */ - if (*cp == '!') { - cp++; - cmdnum = I_SHELL; - } else if (cmdnum == -1) { - sftp_syslog(g_pvar, "Invalid command."); - return -1; - } - - /* Get arguments and parse flags */ - *lflag = *pflag = *rflag = *hflag = *n_arg = 0; - *path1 = *path2 = NULL; - optidx = 1; - switch (cmdnum) { -#if 0 - case I_GET: - case I_PUT: - if ((optidx = parse_getput_flags(cmd, argv, argc, - pflag, rflag)) == -1) - return -1; - /* Get first pathname (mandatory) */ - if (argc - optidx < 1) { - error("You must specify at least one path after a " - "%s command.", cmd); - return -1; - } - *path1 = xstrdup(argv[optidx]); - /* Get second pathname (optional) */ - if (argc - optidx > 1) { - *path2 = xstrdup(argv[optidx + 1]); - /* Destination is not globbed */ - undo_glob_escape(*path2); - } - break; - case I_LINK: - if ((optidx = parse_link_flags(cmd, argv, argc, sflag)) == -1) - return -1; - case I_SYMLINK: - case I_RENAME: - if (argc - optidx < 2) { - error("You must specify two paths after a %s " - "command.", cmd); - return -1; - } - *path1 = xstrdup(argv[optidx]); - *path2 = xstrdup(argv[optidx + 1]); - /* Paths are not globbed */ - undo_glob_escape(*path1); - undo_glob_escape(*path2); - break; - case I_RM: - case I_MKDIR: - case I_RMDIR: - case I_CHDIR: - case I_LCHDIR: - case I_LMKDIR: - /* Get pathname (mandatory) */ - if (argc - optidx < 1) { - error("You must specify a path after a %s command.", - cmd); - return -1; - } - *path1 = xstrdup(argv[optidx]); - /* Only "rm" globs */ - if (cmdnum != I_RM) - undo_glob_escape(*path1); - break; - case I_DF: - if ((optidx = parse_df_flags(cmd, argv, argc, hflag, - iflag)) == -1) - return -1; - /* Default to current directory if no path specified */ - if (argc - optidx < 1) - *path1 = NULL; - else { - *path1 = xstrdup(argv[optidx]); - undo_glob_escape(*path1); - } - break; - case I_LS: - if ((optidx = parse_ls_flags(argv, argc, lflag)) == -1) - return(-1); - /* Path is optional */ - if (argc - optidx > 0) - *path1 = xstrdup(argv[optidx]); - break; - case I_LLS: - /* Skip ls command and following whitespace */ - cp = cp + strlen(cmd) + strspn(cp, WHITESPACE); - case I_SHELL: - /* Uses the rest of the line */ - break; - case I_LUMASK: - case I_CHMOD: - base = 8; - case I_CHOWN: - case I_CHGRP: - /* Get numeric arg (mandatory) */ - if (argc - optidx < 1) - goto need_num_arg; - errno = 0; - l = strtol(argv[optidx], &cp2, base); - if (cp2 == argv[optidx] || *cp2 != '\0' || - ((l == LONG_MIN || l == LONG_MAX) && errno == ERANGE) || - l < 0) { - need_num_arg: - error("You must supply a numeric argument " - "to the %s command.", cmd); - return -1; - } - *n_arg = l; - if (cmdnum == I_LUMASK) - break; - /* Get pathname (mandatory) */ - if (argc - optidx < 2) { - error("You must specify a path after a %s command.", - cmd); - return -1; - } - *path1 = xstrdup(argv[optidx + 1]); - break; -#endif - case I_QUIT: - case I_PWD: - case I_LPWD: - case I_HELP: - case I_VERSION: - case I_PROGRESS: - break; - default: - //fatal("Command not implemented"); - return -1; - } - - *cpp = cp; - return(cmdnum); + /* Figure out which command we have */ + for (i = 0; cmds[i].c != NULL; i++) { + if (_strcmpi(cmds[i].c, argv[0]) == 0) + break; + } + cmdnum = cmds[i].n; + cmd = cmds[i].c; + + /* Special case */ + if (*cp == '!') { + cp++; + cmdnum = I_SHELL; + } else if (cmdnum == -1) { + sftp_syslog(g_pvar, "Invalid command."); + return -1; + } + + /* Get arguments and parse flags */ + *lflag = *pflag = *rflag = *hflag = *n_arg = 0; + *path1 = *path2 = NULL; + optidx = 1; + switch (cmdnum) { +#if 0 + case I_GET: + case I_PUT: + if ((optidx = parse_getput_flags(cmd, argv, argc, + pflag, rflag)) == -1) + return -1; + /* Get first pathname (mandatory) */ + if (argc - optidx < 1) { + error("You must specify at least one path after a " + "%s command.", cmd); + return -1; + } + *path1 = xstrdup(argv[optidx]); + /* Get second pathname (optional) */ + if (argc - optidx > 1) { + *path2 = xstrdup(argv[optidx + 1]); + /* Destination is not globbed */ + undo_glob_escape(*path2); + } + break; + case I_LINK: + if ((optidx = parse_link_flags(cmd, argv, argc, sflag)) == -1) + return -1; + case I_SYMLINK: + case I_RENAME: + if (argc - optidx < 2) { + error("You must specify two paths after a %s " + "command.", cmd); + return -1; + } + *path1 = xstrdup(argv[optidx]); + *path2 = xstrdup(argv[optidx + 1]); + /* Paths are not globbed */ + undo_glob_escape(*path1); + undo_glob_escape(*path2); + break; + case I_RM: + case I_MKDIR: + case I_RMDIR: + case I_CHDIR: + case I_LCHDIR: + case I_LMKDIR: + /* Get pathname (mandatory) */ + if (argc - optidx < 1) { + error("You must specify a path after a %s command.", + cmd); + return -1; + } + *path1 = xstrdup(argv[optidx]); + /* Only "rm" globs */ + if (cmdnum != I_RM) + undo_glob_escape(*path1); + break; + case I_DF: + if ((optidx = parse_df_flags(cmd, argv, argc, hflag, + iflag)) == -1) + return -1; + /* Default to current directory if no path specified */ + if (argc - optidx < 1) + *path1 = NULL; + else { + *path1 = xstrdup(argv[optidx]); + undo_glob_escape(*path1); + } + break; + case I_LS: + if ((optidx = parse_ls_flags(argv, argc, lflag)) == -1) + return(-1); + /* Path is optional */ + if (argc - optidx > 0) + *path1 = xstrdup(argv[optidx]); + break; + case I_LLS: + /* Skip ls command and following whitespace */ + cp = cp + strlen(cmd) + strspn(cp, WHITESPACE); + case I_SHELL: + /* Uses the rest of the line */ + break; + case I_LUMASK: + case I_CHMOD: + base = 8; + case I_CHOWN: + case I_CHGRP: + /* Get numeric arg (mandatory) */ + if (argc - optidx < 1) + goto need_num_arg; + errno = 0; + l = strtol(argv[optidx], &cp2, base); + if (cp2 == argv[optidx] || *cp2 != '\0' || + ((l == LONG_MIN || l == LONG_MAX) && errno == ERANGE) || + l < 0) { + need_num_arg: + error("You must supply a numeric argument " + "to the %s command.", cmd); + return -1; + } + *n_arg = l; + if (cmdnum == I_LUMASK) + break; + /* Get pathname (mandatory) */ + if (argc - optidx < 2) { + error("You must specify a path after a %s command.", + cmd); + return -1; + } + *path1 = xstrdup(argv[optidx + 1]); + break; +#endif + case I_QUIT: + case I_PWD: + case I_LPWD: + case I_HELP: + case I_VERSION: + case I_PROGRESS: + break; + default: + //fatal("Command not implemented"); + return -1; + } + + *cpp = cp; + return(cmdnum); } @@ -818,9 +818,9 @@ int pflag = 0, rflag = 0, lflag = 0, iflag = 0, hflag = 0, sflag = 0; int cmdnum, i = 0; unsigned long n_arg = 0; - //Attrib a, *aa; - char path_buf[1024] = {0}; - int err = 0; + //Attrib a, *aa; + char path_buf[1024] = {0}; + int err = 0; //glob_t g; int err_abort; @@ -849,229 +849,229 @@ cmdnum = parse_args(&cmd, &pflag, &rflag, &lflag, &iflag, &hflag, &sflag, &n_arg, &path1, &path2); - if (iflag != 0) - err_abort = 0; - - //memset(&g, 0, sizeof(g)); - - /* Perform command */ - switch (cmdnum) { - case 0: - /* Blank line */ - break; - case -1: - /* Unrecognized command */ - err = -1; - break; -#if 0 - case I_GET: - err = process_get(conn, path1, path2, *pwd, pflag, rflag); - break; - case I_PUT: - err = process_put(conn, path1, path2, *pwd, pflag, rflag); - break; - case I_RENAME: - path1 = make_absolute(path1, *pwd); - path2 = make_absolute(path2, *pwd); - err = do_rename(conn, path1, path2); - break; - case I_SYMLINK: - sflag = 1; - case I_LINK: - path1 = make_absolute(path1, *pwd); - path2 = make_absolute(path2, *pwd); - err = (sflag ? do_symlink : do_hardlink)(conn, path1, path2); - break; - case I_RM: - path1 = make_absolute(path1, *pwd); - remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); - for (i = 0; g.gl_pathv[i] && !interrupted; i++) { - printf("Removing %s\n", g.gl_pathv[i]); - err = do_rm(conn, g.gl_pathv[i]); - if (err != 0 && err_abort) - break; - } - break; - case I_MKDIR: - path1 = make_absolute(path1, *pwd); - attrib_clear(&a); - a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS; - a.perm = 0777; - err = do_mkdir(conn, path1, &a, 1); - break; - case I_RMDIR: - path1 = make_absolute(path1, *pwd); - err = do_rmdir(conn, path1); - break; - case I_CHDIR: - path1 = make_absolute(path1, *pwd); - if ((tmp = do_realpath(conn, path1)) == NULL) { - err = 1; - break; - } - if ((aa = do_stat(conn, tmp, 0)) == NULL) { - xfree(tmp); - err = 1; - break; - } - if (!(aa->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)) { - error("Can't change directory: Can't check target"); - xfree(tmp); - err = 1; - break; - } - if (!S_ISDIR(aa->perm)) { - error("Can't change directory: \"%s\" is not " - "a directory", tmp); - xfree(tmp); - err = 1; - break; - } - xfree(*pwd); - *pwd = tmp; - break; - case I_LS: - if (!path1) { - do_ls_dir(conn, *pwd, *pwd, lflag); - break; - } - - /* Strip pwd off beginning of non-absolute paths */ - tmp = NULL; - if (*path1 != '/') - tmp = *pwd; - - path1 = make_absolute(path1, *pwd); - err = do_globbed_ls(conn, path1, tmp, lflag); - break; - case I_DF: - /* Default to current directory if no path specified */ - if (path1 == NULL) - path1 = xstrdup(*pwd); - path1 = make_absolute(path1, *pwd); - err = do_df(conn, path1, hflag, iflag); - break; - case I_LCHDIR: - if (chdir(path1) == -1) { - error("Couldn't change local directory to " - "\"%s\": %s", path1, strerror(errno)); - err = 1; - } - break; - case I_LMKDIR: - if (mkdir(path1, 0777) == -1) { - error("Couldn't create local directory " - "\"%s\": %s", path1, strerror(errno)); - err = 1; - } - break; - case I_LLS: - local_do_ls(cmd); - break; - case I_SHELL: - local_do_shell(cmd); - break; - case I_LUMASK: - umask(n_arg); - printf("Local umask: %03lo\n", n_arg); - break; - case I_CHMOD: - path1 = make_absolute(path1, *pwd); - attrib_clear(&a); - a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS; - a.perm = n_arg; - remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); - for (i = 0; g.gl_pathv[i] && !interrupted; i++) { - printf("Changing mode on %s\n", g.gl_pathv[i]); - err = do_setstat(conn, g.gl_pathv[i], &a); - if (err != 0 && err_abort) - break; - } - break; - case I_CHOWN: - case I_CHGRP: - path1 = make_absolute(path1, *pwd); - remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); - for (i = 0; g.gl_pathv[i] && !interrupted; i++) { - if (!(aa = do_stat(conn, g.gl_pathv[i], 0))) { - if (err_abort) { - err = -1; - break; - } else - continue; - } - if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) { - error("Can't get current ownership of " - "remote file \"%s\"", g.gl_pathv[i]); - if (err_abort) { - err = -1; - break; - } else - continue; - } - aa->flags &= SSH2_FILEXFER_ATTR_UIDGID; - if (cmdnum == I_CHOWN) { - printf("Changing owner on %s\n", g.gl_pathv[i]); - aa->uid = n_arg; - } else { - printf("Changing group on %s\n", g.gl_pathv[i]); - aa->gid = n_arg; - } - err = do_setstat(conn, g.gl_pathv[i], aa); - if (err != 0 && err_abort) - break; - } - break; - case I_PWD: - printf("Remote working directory: %s\n", *pwd); - break; - case I_LPWD: - if (!getcwd(path_buf, sizeof(path_buf))) { - error("Couldn't get local cwd: %s", strerror(errno)); - err = -1; - break; - } - printf("Local working directory: %s\n", path_buf); - break; -#endif - case I_QUIT: - /* Processed below */ - break; - case I_HELP: - help(); - break; - case I_VERSION: - printf("SFTP protocol version %u\n", sftp_proto_version(&g_channel->sftp)); - break; -#if 0 - case I_PROGRESS: - showprogress = !showprogress; - if (showprogress) - printf("Progress meter enabled\n"); - else - printf("Progress meter disabled\n"); - break; -#endif - default: - //fatal("%d is not implemented", cmdnum); - err = -1; - } - -#if 0 - if (g.gl_pathc) - globfree(&g); - if (path1) - xfree(path1); - if (path2) - xfree(path2); - - /* If an unignored error occurs in batch mode we should abort. */ - if (err_abort && err != 0) - return (-1); - else if (cmdnum == I_QUIT) - return (1); -#endif + if (iflag != 0) + err_abort = 0; + //memset(&g, 0, sizeof(g)); + + /* Perform command */ + switch (cmdnum) { + case 0: + /* Blank line */ + break; + case -1: + /* Unrecognized command */ + err = -1; + break; +#if 0 + case I_GET: + err = process_get(conn, path1, path2, *pwd, pflag, rflag); + break; + case I_PUT: + err = process_put(conn, path1, path2, *pwd, pflag, rflag); + break; + case I_RENAME: + path1 = make_absolute(path1, *pwd); + path2 = make_absolute(path2, *pwd); + err = do_rename(conn, path1, path2); + break; + case I_SYMLINK: + sflag = 1; + case I_LINK: + path1 = make_absolute(path1, *pwd); + path2 = make_absolute(path2, *pwd); + err = (sflag ? do_symlink : do_hardlink)(conn, path1, path2); + break; + case I_RM: + path1 = make_absolute(path1, *pwd); + remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); + for (i = 0; g.gl_pathv[i] && !interrupted; i++) { + printf("Removing %s\n", g.gl_pathv[i]); + err = do_rm(conn, g.gl_pathv[i]); + if (err != 0 && err_abort) + break; + } + break; + case I_MKDIR: + path1 = make_absolute(path1, *pwd); + attrib_clear(&a); + a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS; + a.perm = 0777; + err = do_mkdir(conn, path1, &a, 1); + break; + case I_RMDIR: + path1 = make_absolute(path1, *pwd); + err = do_rmdir(conn, path1); + break; + case I_CHDIR: + path1 = make_absolute(path1, *pwd); + if ((tmp = do_realpath(conn, path1)) == NULL) { + err = 1; + break; + } + if ((aa = do_stat(conn, tmp, 0)) == NULL) { + xfree(tmp); + err = 1; + break; + } + if (!(aa->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)) { + error("Can't change directory: Can't check target"); + xfree(tmp); + err = 1; + break; + } + if (!S_ISDIR(aa->perm)) { + error("Can't change directory: \"%s\" is not " + "a directory", tmp); + xfree(tmp); + err = 1; + break; + } + xfree(*pwd); + *pwd = tmp; + break; + case I_LS: + if (!path1) { + do_ls_dir(conn, *pwd, *pwd, lflag); + break; + } + + /* Strip pwd off beginning of non-absolute paths */ + tmp = NULL; + if (*path1 != '/') + tmp = *pwd; + + path1 = make_absolute(path1, *pwd); + err = do_globbed_ls(conn, path1, tmp, lflag); + break; + case I_DF: + /* Default to current directory if no path specified */ + if (path1 == NULL) + path1 = xstrdup(*pwd); + path1 = make_absolute(path1, *pwd); + err = do_df(conn, path1, hflag, iflag); + break; + case I_LCHDIR: + if (chdir(path1) == -1) { + error("Couldn't change local directory to " + "\"%s\": %s", path1, strerror(errno)); + err = 1; + } + break; + case I_LMKDIR: + if (mkdir(path1, 0777) == -1) { + error("Couldn't create local directory " + "\"%s\": %s", path1, strerror(errno)); + err = 1; + } + break; + case I_LLS: + local_do_ls(cmd); + break; + case I_SHELL: + local_do_shell(cmd); + break; + case I_LUMASK: + umask(n_arg); + printf("Local umask: %03lo\n", n_arg); + break; + case I_CHMOD: + path1 = make_absolute(path1, *pwd); + attrib_clear(&a); + a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS; + a.perm = n_arg; + remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); + for (i = 0; g.gl_pathv[i] && !interrupted; i++) { + printf("Changing mode on %s\n", g.gl_pathv[i]); + err = do_setstat(conn, g.gl_pathv[i], &a); + if (err != 0 && err_abort) + break; + } + break; + case I_CHOWN: + case I_CHGRP: + path1 = make_absolute(path1, *pwd); + remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); + for (i = 0; g.gl_pathv[i] && !interrupted; i++) { + if (!(aa = do_stat(conn, g.gl_pathv[i], 0))) { + if (err_abort) { + err = -1; + break; + } else + continue; + } + if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) { + error("Can't get current ownership of " + "remote file \"%s\"", g.gl_pathv[i]); + if (err_abort) { + err = -1; + break; + } else + continue; + } + aa->flags &= SSH2_FILEXFER_ATTR_UIDGID; + if (cmdnum == I_CHOWN) { + printf("Changing owner on %s\n", g.gl_pathv[i]); + aa->uid = n_arg; + } else { + printf("Changing group on %s\n", g.gl_pathv[i]); + aa->gid = n_arg; + } + err = do_setstat(conn, g.gl_pathv[i], aa); + if (err != 0 && err_abort) + break; + } + break; + case I_PWD: + printf("Remote working directory: %s\n", *pwd); + break; + case I_LPWD: + if (!getcwd(path_buf, sizeof(path_buf))) { + error("Couldn't get local cwd: %s", strerror(errno)); + err = -1; + break; + } + printf("Local working directory: %s\n", path_buf); + break; +#endif + case I_QUIT: + /* Processed below */ + break; + case I_HELP: + help(); + break; + case I_VERSION: + printf("SFTP protocol version %u\n", sftp_proto_version(&g_channel->sftp)); + break; +#if 0 + case I_PROGRESS: + showprogress = !showprogress; + if (showprogress) + printf("Progress meter enabled\n"); + else + printf("Progress meter disabled\n"); + break; +#endif + default: + //fatal("%d is not implemented", cmdnum); + err = -1; + } + +#if 0 + if (g.gl_pathc) + globfree(&g); + if (path1) + xfree(path1); + if (path2) + xfree(path2); + + /* If an unignored error occurs in batch mode we should abort. */ + if (err_abort && err != 0) + return (-1); + else if (cmdnum == I_QUIT) + return (1); +#endif + return 0L; } Modified: trunk/ttssh2/ttxssh/ssh.c =================================================================== --- trunk/ttssh2/ttxssh/ssh.c 2012-10-13 15:37:56 UTC (rev 5038) +++ trunk/ttssh2/ttxssh/ssh.c 2012-10-13 16:18:29 UTC (rev 5039) @@ -209,9 +209,9 @@ break; if (c->local_num == -1) { // shell or SCP - SSH2_send_channel_data(pvar, c, buffer_ptr(ch->msg), size); + SSH2_send_channel_data(pvar, c, buffer_ptr(ch->msg), size, TRUE); } else { // port-forwarding - SSH_channel_send(pvar, c->local_num, -1, buffer_ptr(ch->msg), size); + SSH_channel_send(pvar, c->local_num, -1, buffer_ptr(ch->msg), size, TRUE); } c->bufchain = ch->next; @@ -2982,7 +2982,7 @@ } else { // for SSH2(yutaka) Channel_t *c = ssh2_channel_lookup(pvar->shell_id); - SSH2_send_channel_data(pvar, c, (unsigned char *)buf, buflen); + SSH2_send_channel_data(pvar, c, (unsigned char *)buf, buflen, 0); } } @@ -3218,7 +3218,7 @@ } -void SSH2_send_channel_data(PTInstVar pvar, Channel_t *c, unsigned char FAR * buf, unsigned int buflen) +void SSH2_send_channel_data(PTInstVar pvar, Channel_t *c, unsigned char FAR * buf, unsigned int buflen, int retry) { buffer_t *msg; unsigned char *outmsg; @@ -3237,11 +3237,21 @@ if (c == NULL) return; + // \x83\x8A\x83g\x83\x89\x83C\x82ł͂Ȃ\xA2\x81A\x92ʏ\xED\x82̃p\x83P\x83b\x83g\x91\x97\x90M\x82̍ہA\x88ȑO\x91\x97\x82\xEA\x82Ȃ\xA9\x82\xC1\x82\xBD\x83f\x81[\x83^\x82\xAA + // \x83\x8A\x83\x93\x83N\x83h\x83\x8A\x83X\x83g\x82Ɏc\x82\xC1\x82Ă\xA2\x82\xE9\x82悤\x82ł\xA0\x82\xEA\x82A\x83\x8A\x83X\x83g\x82̖\x96\x94\xF6\x82Ɍq\x82\xAE\x81B + // \x82\xB1\x82\xEA\x82ɂ\xE6\x82\xE8\x83p\x83P\x83b\x83g\x82\xAA\x89\xF3\x82ꂽ\x82悤\x82Ɍ\xA9\x82\xA6\x82錻\x8Fۂ\xAA\x89\xFC\x91P\x82\xB3\x82\xEA\x82\xE9\x81B + // (2012.10.14 yutaka) + if (retry == 0 && c->bufchain) { + ssh2_channel_add_bufchain(c, buf, buflen); + return; + } + if ((unsigned int)buflen > c->remote_window) { - unsigned int offset = c->remote_window; + unsigned int offset = 0; // \x91\x97\x82\xEA\x82Ȃ\xA2\x83f\x81[\x83^\x82͂\xA2\x82\xC1\x82\xBD\x82\xF1\x95ۑ\xB6\x82\xB5\x82Ă\xA8\x82\xAD ssh2_channel_add_bufchain(c, buf + offset, buflen - offset); buflen = offset; + return; } if (buflen > 0) { msg = buffer_init(); @@ -3276,7 +3286,7 @@ /* support for port forwarding */ void SSH_channel_send(PTInstVar pvar, int channel_num, uint32 remote_channel_num, - unsigned char FAR * buf, int len) + unsigned char FAR * buf, int len, int retry) { if (SSHv1(pvar)) { unsigned char FAR *outmsg = @@ -3323,7 +3333,7 @@ } else { // \x83|\x81[\x83g\x83t\x83H\x83\x8F\x81[\x83f\x83B\x83\x93\x83O\x82ɂ\xA8\x82\xA2\x82ăN\x83\x89\x83C\x83A\x83\x93\x83g\x82\xA9\x82\xE7\x82̑\x97\x90M\x97v\x8B\x81\x82\xF0\x81ASSH\x92ʐM\x82ɏ悹\x82ăT\x81[\x83o\x82܂ő\x97\x82\xE8\x93͂\xAF\x82\xE9\x81B Channel_t *c = ssh2_local_channel_lookup(channel_num); - SSH2_send_channel_data(pvar, c, buf, len); + SSH2_send_channel_data(pvar, c, buf, len, retry); } } @@ -7280,7 +7290,7 @@ // (2007.12.27 yutaka) if (c->scp.dir == FROMREMOTE) { char ch = '\0'; - SSH2_send_channel_data(pvar, c, &ch, 1); + SSH2_send_channel_data(pvar, c, &ch, 1, 0); } } else if (c->type == TYPE_SFTP) { @@ -7581,7 +7591,7 @@ { scp_dlg_parm_t *parm = (scp_dlg_parm_t *)wp; - SSH2_send_channel_data(parm->pvar, parm->c, parm->buf, parm->buflen); + SSH2_send_channel_data(parm->pvar, parm->c, parm->buf, parm->buflen, 0); } return TRUE; break; @@ -7787,7 +7797,7 @@ (unsigned long)c->scp.filestat.st_mtime, (unsigned long)c->scp.filestat.st_atime); c->scp.state = SCP_TIMESTAMP; - SSH2_send_channel_data(pvar, c, buf, strlen(buf)); + SSH2_send_channel_data(pvar, c, buf, strlen(buf), 0); } else if (c->scp.state == SCP_TIMESTAMP) { char buf[128]; @@ -7796,7 +7806,7 @@ c->scp.filestat.st_size, c->scp.localfile); c->scp.state = SCP_FILEINFO; - SSH2_send_channel_data(pvar, c, buf, strlen(buf)); + SSH2_send_channel_data(pvar, c, buf, strlen(buf), 0); } else if (c->scp.state == SCP_FILEINFO) { HWND hDlgWnd; @@ -8017,7 +8027,7 @@ reply: ch = '\0'; - SSH2_send_channel_data(pvar, c, &ch, 1); + SSH2_send_channel_data(pvar, c, &ch, 1, 0); return TRUE; } @@ -8657,11 +8667,11 @@ } if (SSHv2(pvar)) { - SSH2_send_channel_data(pvar, c, response, resplen); + SSH2_send_channel_data(pvar, c, response, resplen, 0); } else { SSH_channel_send(pvar, local_channel_num, fc->remote_num, - response, resplen); + response, resplen, 0); } safefree(response); Modified: trunk/ttssh2/ttxssh/ssh.h =================================================================== --- trunk/ttssh2/ttxssh/ssh.h 2012-10-13 15:37:56 UTC (rev 5038) +++ trunk/ttssh2/ttxssh/ssh.h 2012-10-13 16:18:29 UTC (rev 5039) @@ -572,7 +572,7 @@ /* len must be <= SSH_MAX_SEND_PACKET_SIZE */ void SSH_channel_send(PTInstVar pvar, int channel_num, uint32 remote_channel_num, - unsigned char FAR * buf, int len); + unsigned char FAR * buf, int len, int retry); void SSH_fail_channel_open(PTInstVar pvar, uint32 remote_channel_num); void SSH_confirm_channel_open(PTInstVar pvar, uint32 remote_channel_num, uint32 local_channel_num); void SSH_channel_output_eof(PTInstVar pvar, uint32 remote_channel_num); @@ -701,7 +701,7 @@ unsigned char FAR *begin_send_packet(PTInstVar pvar, int type, int len); void finish_send_packet_special(PTInstVar pvar, int skip_compress); -void SSH2_send_channel_data(PTInstVar pvar, Channel_t *c, unsigned char FAR * buf, unsigned int buflen); +void SSH2_send_channel_data(PTInstVar pvar, Channel_t *c, unsigned char FAR * buf, unsigned int buflen, int retry); #define finish_send_packet(pvar) finish_send_packet_special((pvar), 0) #define get_payload_uint32(pvar, offset) get_uint32_MSBfirst((pvar)->ssh_state.payload + (offset))