=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/ssh/sftp.c,v retrieving revision 1.45.2.2 retrieving revision 1.46 diff -u -r1.45.2.2 -r1.46 --- src/usr.bin/ssh/sftp.c 2005/03/10 17:15:04 1.45.2.2 +++ src/usr.bin/ssh/sftp.c 2004/05/19 12:17:33 1.46 @@ -16,10 +16,9 @@ #include "includes.h" -RCSID("$OpenBSD: sftp.c,v 1.45.2.2 2005/03/10 17:15:04 brad Exp $"); +RCSID("$OpenBSD: sftp.c,v 1.46 2004/05/19 12:17:33 djm Exp $"); #include -#include #include "buffer.h" #include "xmalloc.h" @@ -52,28 +51,16 @@ /* SIGINT received during command processing */ volatile sig_atomic_t interrupted = 0; -/* I wish qsort() took a separate ctx for the comparison function...*/ -int sort_flag; - int remote_glob(struct sftp_conn *, const char *, int, int (*)(const char *, int), glob_t *); /* proto for sftp-glob.c */ /* Separators for interactive commands */ #define WHITESPACE " \t\r\n" -/* ls flags */ -#define LS_LONG_VIEW 0x01 /* Full view ala ls -l */ -#define LS_SHORT_VIEW 0x02 /* Single row view ala ls -1 */ -#define LS_NUMERIC_VIEW 0x04 /* Long view with numeric uid/gid */ -#define LS_NAME_SORT 0x08 /* Sort by name (default) */ -#define LS_TIME_SORT 0x10 /* Sort by mtime */ -#define LS_SIZE_SORT 0x20 /* Sort by file size */ -#define LS_REVERSE_SORT 0x40 /* Reverse sort order */ -#define LS_SHOW_ALL 0x80 /* Don't skip filenames starting with '.' */ +/* Define what type of ls view (0 - multi-column) */ +#define LONG_VIEW 1 /* Full view ala ls -l */ +#define SHORT_VIEW 2 /* Single row view ala ls -1 */ -#define VIEW_FLAGS (LS_LONG_VIEW|LS_SHORT_VIEW|LS_NUMERIC_VIEW) -#define SORT_FLAGS (LS_NAME_SORT|LS_TIME_SORT|LS_SIZE_SORT) - /* Commands for interactive mode */ #define I_CHDIR 1 #define I_CHGRP 2 @@ -145,10 +132,8 @@ static void killchild(int signo) { - if (sshpid > 1) { + if (sshpid > 1) kill(sshpid, SIGTERM); - waitpid(sshpid, NULL, 0); - } _exit(1); } @@ -157,11 +142,9 @@ cmd_interrupt(int signo) { const char msg[] = "\rInterrupt \n"; - int olderrno = errno; write(STDERR_FILENO, msg, sizeof(msg) - 1); interrupted = 1; - errno = olderrno; } static void @@ -261,7 +244,7 @@ return (xstrdup(path)); len = strlen(strip); - if (strncmp(path, strip, len) == 0) { + if (strip != NULL && strncmp(path, strip, len) == 0) { if (strip[len - 1] != '/' && path[len] == '/') len++; return (xstrdup(path + len)); @@ -288,13 +271,13 @@ static char * make_absolute(char *p, char *pwd) { - char *abs_str; + char *abs; /* Derelativise */ if (p && p[0] != '/') { - abs_str = path_append(pwd, p); + abs = path_append(pwd, p); xfree(p); - return(abs_str); + return(abs); } else return(p); } @@ -347,42 +330,16 @@ { const char *cp = *cpp; - /* Defaults */ - *lflag = LS_NAME_SORT; - /* Check for flags */ if (cp++[0] == '-') { for(; strchr(WHITESPACE, *cp) == NULL; cp++) { switch (*cp) { case 'l': - *lflag &= ~VIEW_FLAGS; - *lflag |= LS_LONG_VIEW; + *lflag = LONG_VIEW; break; case '1': - *lflag &= ~VIEW_FLAGS; - *lflag |= LS_SHORT_VIEW; + *lflag = SHORT_VIEW; break; - case 'n': - *lflag &= ~VIEW_FLAGS; - *lflag |= LS_NUMERIC_VIEW|LS_LONG_VIEW; - break; - case 'S': - *lflag &= ~SORT_FLAGS; - *lflag |= LS_SIZE_SORT; - break; - case 't': - *lflag &= ~SORT_FLAGS; - *lflag |= LS_TIME_SORT; - break; - case 'r': - *lflag |= LS_REVERSE_SORT; - break; - case 'f': - *lflag &= ~SORT_FLAGS; - break; - case 'a': - *lflag |= LS_SHOW_ALL; - break; default: error("Invalid flag -%c", *cp); return(-1); @@ -429,7 +386,7 @@ i++; if (cp[i] != '\'' && cp[i] != '\"' && cp[i] != '\\') { - error("Bad escaped character '\\%c'", + error("Bad escaped character '\%c'", cp[i]); goto fail; } @@ -642,17 +599,8 @@ { SFTP_DIRENT *a = *(SFTP_DIRENT **)aa; SFTP_DIRENT *b = *(SFTP_DIRENT **)bb; - int rmul = sort_flag & LS_REVERSE_SORT ? -1 : 1; -#define NCMP(a,b) (a == b ? 0 : (a < b ? 1 : -1)) - if (sort_flag & LS_NAME_SORT) - return (rmul * strcmp(a->filename, b->filename)); - else if (sort_flag & LS_TIME_SORT) - return (rmul * NCMP(a->a.mtime, b->a.mtime)); - else if (sort_flag & LS_SIZE_SORT) - return (rmul * NCMP(a->a.size, b->a.size)); - - fatal("Unknown ls sort type"); + return (strcmp(a->filename, b->filename)); } /* sftp ls.1 replacement for directories */ @@ -665,16 +613,14 @@ if ((n = do_readdir(conn, path, &d)) != 0) return (n); - if (!(lflag & LS_SHORT_VIEW)) { + if (!(lflag & SHORT_VIEW)) { int m = 0, width = 80; struct winsize ws; char *tmp; /* Count entries for sort and find longest filename */ - for (n = 0; d[n] != NULL; n++) { - if (d[n]->filename[0] != '.' || (lflag & LS_SHOW_ALL)) - m = MAX(m, strlen(d[n]->filename)); - } + for (n = 0; d[n] != NULL; n++) + m = MAX(m, strlen(d[n]->filename)); /* Add any subpath that also needs to be counted */ tmp = path_strip(path, strip_path); @@ -690,33 +636,24 @@ colspace = MIN(colspace, width); } - if (lflag & SORT_FLAGS) { - sort_flag = lflag & (SORT_FLAGS|LS_REVERSE_SORT); - qsort(d, n, sizeof(*d), sdirent_comp); - } + qsort(d, n, sizeof(*d), sdirent_comp); for (n = 0; d[n] != NULL && !interrupted; n++) { char *tmp, *fname; - if (d[n]->filename[0] == '.' && !(lflag & LS_SHOW_ALL)) - continue; - tmp = path_append(path, d[n]->filename); fname = path_strip(tmp, strip_path); xfree(tmp); - if (lflag & LS_LONG_VIEW) { - if (lflag & LS_NUMERIC_VIEW) { - char *lname; - struct stat sb; + if (lflag & LONG_VIEW) { + char *lname; + struct stat sb; - memset(&sb, 0, sizeof(sb)); - attrib_to_stat(&d[n]->a, &sb); - lname = ls_file(fname, &sb, 1); - printf("%s\n", lname); - xfree(lname); - } else - printf("%s\n", d[n]->longname); + memset(&sb, 0, sizeof(sb)); + attrib_to_stat(&d[n]->a, &sb); + lname = ls_file(fname, &sb, 1); + printf("%s\n", lname); + xfree(lname); } else { printf("%-*s", colspace, fname); if (c >= columns) { @@ -729,7 +666,7 @@ xfree(fname); } - if (!(lflag & LS_LONG_VIEW) && (c != 1)) + if (!(lflag & LONG_VIEW) && (c != 1)) printf("\n"); free_sftp_dirents(d); @@ -743,14 +680,12 @@ { glob_t g; int i, c = 1, colspace = 0, columns = 1; - Attrib *a = NULL; + Attrib *a; memset(&g, 0, sizeof(g)); if (remote_glob(conn, path, GLOB_MARK|GLOB_NOCHECK|GLOB_BRACE, - NULL, &g) || (g.gl_pathc && !g.gl_matchc)) { - if (g.gl_pathc) - globfree(&g); + NULL, &g)) { error("Can't ls: \"%s\" not found", path); return (-1); } @@ -759,25 +694,23 @@ goto out; /* - * If the glob returns a single match and it is a directory, - * then just list its contents. + * If the glob returns a single match, which is the same as the + * input glob, and it is a directory, then just list its contents */ - if (g.gl_matchc == 1) { - if ((a = do_lstat(conn, g.gl_pathv[0], 1)) == NULL) { + if (g.gl_pathc == 1 && + strncmp(path, g.gl_pathv[0], strlen(g.gl_pathv[0]) - 1) == 0) { + if ((a = do_lstat(conn, path, 1)) == NULL) { globfree(&g); return (-1); } if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) && S_ISDIR(a->perm)) { - int err; - - err = do_ls_dir(conn, g.gl_pathv[0], strip_path, lflag); globfree(&g); - return (err); + return (do_ls_dir(conn, path, strip_path, lflag)); } } - if (!(lflag & LS_SHORT_VIEW)) { + if (!(lflag & SHORT_VIEW)) { int m = 0, width = 80; struct winsize ws; @@ -793,12 +726,12 @@ colspace = width / columns; } - for (i = 0; g.gl_pathv[i] && !interrupted; i++, a = NULL) { + for (i = 0; g.gl_pathv[i] && !interrupted; i++) { char *fname; fname = path_strip(g.gl_pathv[i], strip_path); - if (lflag & LS_LONG_VIEW) { + if (lflag & LONG_VIEW) { char *lname; struct stat sb; @@ -810,8 +743,7 @@ * that the server returns as well as the filenames. */ memset(&sb, 0, sizeof(sb)); - if (a == NULL) - a = do_lstat(conn, g.gl_pathv[i], 1); + a = do_lstat(conn, g.gl_pathv[i], 1); if (a != NULL) attrib_to_stat(a, &sb); lname = ls_file(fname, &sb, 1); @@ -828,7 +760,7 @@ xfree(fname); } - if (!(lflag & LS_LONG_VIEW) && (c != 1)) + if (!(lflag & LONG_VIEW) && (c != 1)) printf("\n"); out: @@ -1216,12 +1148,6 @@ return (0); } -static char * -prompt(EditLine *el) -{ - return ("sftp> "); -} - int interactive_loop(int fd_in, int fd_out, char *file1, char *file2) { @@ -1230,26 +1156,7 @@ char cmd[2048]; struct sftp_conn *conn; int err; - EditLine *el = NULL; - History *hl = NULL; - HistEvent hev; - extern char *__progname; - if (!batchmode && isatty(STDIN_FILENO)) { - if ((el = el_init(__progname, stdin, stdout, stderr)) == NULL) - fatal("Couldn't initialise editline"); - if ((hl = history_init()) == NULL) - fatal("Couldn't initialise editline history"); - history(hl, &hev, H_SETSIZE, 100); - el_set(el, EL_HIST, history, hl); - - el_set(el, EL_PROMPT, prompt); - el_set(el, EL_EDITOR, "emacs"); - el_set(el, EL_TERMINAL, NULL); - el_set(el, EL_SIGNAL, 1); - el_source(el, NULL); - } - conn = do_init(fd_in, fd_out, copy_buffer_len, num_requests); if (conn == NULL) fatal("Couldn't initialise connection to server"); @@ -1265,11 +1172,8 @@ if (remote_is_dir(conn, dir) && file2 == NULL) { printf("Changing to: %s\n", dir); snprintf(cmd, sizeof cmd, "cd \"%s\"", dir); - if (parse_dispatch_command(conn, cmd, &pwd, 1) != 0) { - xfree(dir); - xfree(pwd); + if (parse_dispatch_command(conn, cmd, &pwd, 1) != 0) return (-1); - } } else { if (file2 == NULL) snprintf(cmd, sizeof cmd, "get %s", dir); @@ -1291,29 +1195,20 @@ err = 0; for (;;) { char *cp; - const char *line; - int count = 0; signal(SIGINT, SIG_IGN); - if (el == NULL) { - printf("sftp> "); - if (fgets(cmd, sizeof(cmd), infile) == NULL) { - printf("\n"); - break; - } - if (batchmode) /* Echo command */ - printf("%s", cmd); - } else { - if ((line = el_gets(el, &count)) == NULL || count <= 0) - break; - history(hl, &hev, H_ENTER, line); - if (strlcpy(cmd, line, sizeof(cmd)) >= sizeof(cmd)) { - fprintf(stderr, "Error: input line too long\n"); - continue; - } + printf("sftp> "); + + /* XXX: use libedit */ + if (fgets(cmd, sizeof(cmd), infile) == NULL) { + printf("\n"); + break; } + if (batchmode) /* Echo command */ + printf("%s", cmd); + cp = strrchr(cmd, '\n'); if (cp) *cp = '\0'; @@ -1361,7 +1256,7 @@ if ((dup2(c_in, STDIN_FILENO) == -1) || (dup2(c_out, STDOUT_FILENO) == -1)) { fprintf(stderr, "dup2: %s\n", strerror(errno)); - _exit(1); + exit(1); } close(*in); close(*out); @@ -1370,14 +1265,14 @@ /* * The underlying ssh is in the same process group, so we must - * ignore SIGINT if we want to gracefully abort commands, - * otherwise the signal will make it to the ssh process and + * ignore SIGINT if we want to gracefully abort commands, + * otherwise the signal will make it to the ssh process and * kill it too */ signal(SIGINT, SIG_IGN); - execvp(path, args); + execv(path, args); fprintf(stderr, "exec: %s: %s\n", path, strerror(errno)); - _exit(1); + exit(1); } signal(SIGTERM, killchild); @@ -1406,7 +1301,7 @@ main(int argc, char **argv) { int in, out, ch, err; - char *host, *userhost, *cp, *file2 = NULL; + char *host, *userhost, *cp, *file2; int debug_level = 0, sshver = 2; char *file1 = NULL, *sftp_server = NULL; char *ssh_program = _PATH_SSH_PROGRAM, *sftp_direct = NULL; @@ -1456,12 +1351,11 @@ fatal("Batch file already specified."); /* Allow "-" as stdin */ - if (strcmp(optarg, "-") != 0 && + if (strcmp(optarg, "-") != 0 && (infile = fopen(optarg, "r")) == NULL) fatal("%s (%s).", strerror(errno), optarg); showprogress = 0; batchmode = 1; - addargs(&args, "-obatchmode yes"); break; case 'P': sftp_direct = optarg;