guy@sun.uucp (Guy Harris) (06/26/85)
Index: ucb/ftp/cmds.c ucb/ftp/ftp.c ucb/ftp/getpass.c ucb/ftp/main.c 4.2BSD Description: 1) The "!" command has an undocumented feature; if it's invoked in the form "!<command>", the <command> is executed and control returns to "ftp" when it exits. This is nicely consistent with most other UNIX commands (I wish more commands would interpret an undecorated "!" as a request to spawn an interactive subshell, as "ftp" does). However, instead of just handing the <command> to an "sh -c", it tries to do the "glob"bing and tokenizing itself and does an "execvp" directly. This does not work correctly. Also, when invoked without a <command>, it prefixes the shell's name with a "-", causing it to be run as a login shell, which is wrong. (And if the shell is not "sh", it prefixes it with a "+" instead.) 2) If you try to retrieve something into a local file, and you don't have write permission on the file, it tests whether you have write permission on the directory containing that file. However, the test is wrong - if the local file name is a path containing slashes, it does a test on a null pathname rather than on the containing directory. 3) The code that reads reply codes throws some reply codes away; see my previous posting. 4) "ftp" should permit passwords of at least 50 characters in length; see a previous bug posting by, I believe, rws@mit-bold. (I think 4.3BSD almost fixes this, but the code limits passwords to 49 characters.) Repeat-By: 1) Try ftp>!echo "*.c" and notice that it does not print "*.c". Then try ftp>! and do a "ps"; note that you're running "-sh" or "+csh" (or something like that). 2) Try doing a "get" where the target file is not in the current directory and is in a directory where you don't have write permission. It won't complain, but it won't do it either. Fix: Here's an omnibus set of fixes: *** /arch/4.2/usr/src/ucb/ftp/cmds.c Tue Jul 26 21:34:47 1983 --- 4.2.fixed/cmds.c Wed Jun 26 03:17:10 1985 *************** *** 703,709 dest = argv[argc - 1]; argv[argc - 1] = NULL; if (strcmp(dest, "-")) ! if (globulize(&dest) && confirm("local-file", dest)) return; cmd = argv[0][1] == 'l' ? "NLST" : "LIST"; for (mode = "w"; cp = remglob(argc, argv); mode = "a") --- 703,709 ----- dest = argv[argc - 1]; argv[argc - 1] = NULL; if (strcmp(dest, "-")) ! if (!globulize(&dest) || !confirm("local-file", dest)) return; cmd = argv[0][1] == 'l' ? "NLST" : "LIST"; for (mode = "w"; cp = remglob(argc, argv); mode = "a") *************** *** 728,733 close(pid); signal(SIGINT, SIG_DFL); signal(SIGQUIT, SIG_DFL); if (argc <= 1) { shell = getenv("SHELL"); if (shell == NULL) --- 728,739 ----- close(pid); signal(SIGINT, SIG_DFL); signal(SIGQUIT, SIG_DFL); + shell = getenv("SHELL"); + if (shell == NULL) + shell = "/bin/sh"; + namep = rindex(shell,'/'); + if (namep == NULL) + namep = shell; if (argc <= 1) { if (debug) { printf ("%s\n", shell); *************** *** 729,744 signal(SIGINT, SIG_DFL); signal(SIGQUIT, SIG_DFL); if (argc <= 1) { - shell = getenv("SHELL"); - if (shell == NULL) - shell = "/bin/sh"; - namep = rindex(shell,'/'); - if (namep == NULL) - namep = shell; - strcpy(shellnam,"-"); - strcat(shellnam, ++namep); - if (strcmp(namep, "sh") != 0) - shellnam[0] = '+'; if (debug) { printf ("%s\n", shell); fflush (stdout); --- 735,740 ----- if (namep == NULL) namep = shell; if (argc <= 1) { if (debug) { printf ("%s\n", shell); fflush (stdout); *************** *** 743,759 printf ("%s\n", shell); fflush (stdout); } ! execl(shell, shellnam, 0); ! perror(shell); ! exit(1); ! } ! cpp = &argv[1]; ! if (argc > 2) { ! if ((gargs = glob(cpp)) != NULL) ! cpp = gargs; ! if (globerr != NULL) { ! printf("%s\n", globerr); ! exit(1); } } if (debug) { --- 739,755 ----- printf ("%s\n", shell); fflush (stdout); } ! execl(shell, shell, (char *)0); ! } else { ! char *args[4]; /* "sh" "-c" <command> NULL */ ! ! args[0] = shell; ! args[1] = "-c"; ! args[2] = argv[1]; ! args[3] = NULL; ! if (debug) { ! printf("%s -c %s\n", shell, argv[1]); ! fflush(stdout); } execv(shell, args); } *************** *** 755,760 printf("%s\n", globerr); exit(1); } } if (debug) { register char **zip = cpp; --- 751,757 ----- printf("%s -c %s\n", shell, argv[1]); fflush(stdout); } + execv(shell, args); } perror(shell); exit(1); *************** *** 756,772 exit(1); } } ! if (debug) { ! register char **zip = cpp; ! ! printf("%s", *zip); ! while (*++zip != NULL) ! printf(" %s", *zip); ! printf("\n"); ! fflush(stdout); ! } ! execvp(argv[1], cpp); ! perror(argv[1]); exit(1); } if (pid > 0) --- 753,759 ----- } execv(shell, args); } ! perror(shell); exit(1); } if (pid > 0) *** /arch/4.2/usr/src/ucb/ftp/ftp.c Tue Jul 26 21:34:47 1983 --- 4.2.fixed/ftp.c Wed Jun 26 03:46:14 1985 *************** *** 182,189 originalcode = code; continue; } ! if (expecteof || empty(cin)) ! return (n - '0'); } } --- 182,188 ----- originalcode = code; continue; } ! return (n - '0'); } } *************** *** 187,206 } } - empty(f) - FILE *f; - { - long mask; - struct timeval t; - - if (f->_cnt > 0) - return (0); - mask = (1 << fileno(f)); - t.tv_sec = t.tv_usec = 0; - (void) select(20, &mask, 0, 0, &t); - return (mask == 0); - } - jmp_buf sendabort; abortsend() --- 186,191 ----- } } jmp_buf sendabort; abortsend() *************** *** 356,362 oldintr = signal(SIGINT, abortrecv); if (strcmp(local, "-") && *local != '|') if (access(local, 2) < 0) { ! char *dir = rindex(local, '/'); if (dir != NULL) *dir = 0; --- 341,348 ----- oldintr = signal(SIGINT, abortrecv); if (strcmp(local, "-") && *local != '|') if (access(local, 2) < 0) { ! if (errno == ENOENT) { ! char *dir = rindex(local, '/'); if (dir != NULL) *dir = 0; *************** *** 358,366 if (access(local, 2) < 0) { char *dir = rindex(local, '/'); ! if (dir != NULL) ! *dir = 0; ! if (access(dir ? dir : ".", 2) < 0) { perror(local); goto bad; } --- 344,358 ----- if (errno == ENOENT) { char *dir = rindex(local, '/'); ! if (dir != NULL) ! *dir = 0; ! if (access(dir ? local : ".", 2) < 0) { ! perror(local); ! goto bad; ! } ! if (dir != NULL) ! *dir = '/'; ! } else { perror(local); goto bad; } *************** *** 364,371 perror(local); goto bad; } - if (dir != NULL) - *dir = '/'; } if (initconn()) goto bad; --- 356,361 ----- perror(local); goto bad; } } if (initconn()) goto bad; *************** *** 493,499 } if (!sendport) if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, 0, 0) < 0) { ! perror("ftp: setsockopt (resuse address)"); goto bad; } if (bind(data, (char *)&data_addr, sizeof (data_addr), 0) < 0) { --- 483,489 ----- } if (!sendport) if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, 0, 0) < 0) { ! perror("ftp: setsockopt (reuse address)"); goto bad; } if (bind(data, (char *)&data_addr, sizeof (data_addr), 0) < 0) { *** /arch/4.2/usr/src/ucb/ftp/getpass.c Tue Jul 26 21:34:48 1983 --- 4.2.fixed/getpass.c Sun Apr 7 12:22:25 1985 *************** *** 15,21 register char *p; register c; FILE *fi; ! static char pbuf[9]; int (*signal())(); int (*sig)(); --- 15,21 ----- register char *p; register c; FILE *fi; ! static char pbuf[51]; int (*signal())(); int (*sig)(); *************** *** 30,36 stty(fileno(fi), &ttyb); fprintf(stderr, "%s", prompt); fflush(stderr); for (p=pbuf; (c = getc(fi))!='\n' && c!=EOF;) { ! if (p < &pbuf[8]) *p++ = c; } *p = '\0'; --- 30,36 ----- stty(fileno(fi), &ttyb); fprintf(stderr, "%s", prompt); fflush(stderr); for (p=pbuf; (c = getc(fi))!='\n' && c!=EOF;) { ! if (p < &pbuf[50]) *p++ = c; } *p = '\0'; *** /arch/4.2/usr/src/ucb/ftp/main.c Tue Jul 26 21:34:48 1983 --- 4.2.fixed/main.c Sun Apr 7 12:22:26 1985 *************** *** 251,257 argp = margv; stringbase = line; /* scan from first of buffer */ argbase = argbuf; /* store from first of buffer */ ! while (*argp++ = slurpstring()) margc++; } --- 251,261 ----- argp = margv; stringbase = line; /* scan from first of buffer */ argbase = argbuf; /* store from first of buffer */ ! while (*stringbase == ' ' || *stringbase == '\t') ! stringbase++; /* skip initial white space */ ! if (*stringbase == '!') { /* handle shell escapes specially */ ! stringbase++; ! *argp++ = "!"; /* command name is "!" */ margc++; while (*stringbase == ' ' || *stringbase == '\t') stringbase++; /* skip white space */ *************** *** 253,258 argbase = argbuf; /* store from first of buffer */ while (*argp++ = slurpstring()) margc++; } /* --- 257,273 ----- stringbase++; *argp++ = "!"; /* command name is "!" */ margc++; + while (*stringbase == ' ' || *stringbase == '\t') + stringbase++; /* skip white space */ + if (*stringbase != '\0') { + *argp++ = stringbase; /* argument is entire command string */ + margc++; + } + *argp++ = NULL; + } else { + while (*argp++ = slurpstring()) + margc++; + } } /* *************** *** 268,277 register char *ap = argbase; char *tmp = argbase; /* will return this if token found */ - if (*sb == '!') { /* recognize ! as a token for shell */ - stringbase++; - return ("!"); - } S0: switch (*sb) { --- 283,288 ----- register char *ap = argbase; char *tmp = argbase; /* will return this if token found */ S0: switch (*sb) {