[BACK]Return to scp.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

Diff for /src/usr.bin/ssh/scp.c between version 1.91.2.2 and 1.92

version 1.91.2.2, 2003/09/16 21:20:27 version 1.92, 2002/11/07 22:35:38
Line 52 
Line 52 
  * 2. Redistributions in binary form must reproduce the above copyright   * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the   *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.   *    documentation and/or other materials provided with the distribution.
  * 3. Neither the name of the University nor the names of its contributors   * 3. All advertising materials mentioning features or use of this software
    *    must display the following acknowledgement:
    *      This product includes software developed by the University of
    *      California, Berkeley and its contributors.
    * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software   *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.   *    without specific prior written permission.
  *   *
Line 78 
Line 82 
 #include "pathnames.h"  #include "pathnames.h"
 #include "log.h"  #include "log.h"
 #include "misc.h"  #include "misc.h"
 #include "progressmeter.h"  
   
 int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc);  /* For progressmeter() -- number of seconds before xfer considered "stalled" */
   #define STALLTIME       5
   /* alarm() interval for updating progress meter */
   #define PROGRESSTIME    1
   
 void bwlimit(int);  /* Visual statistics about files as they are transferred. */
   void progressmeter(int);
   
   /* Returns width of the terminal (for progress meter calculations). */
   int getttywidth(void);
   int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc);
   
 /* Struct for addargs */  /* Struct for addargs */
 arglist args;  arglist args;
   
 /* Bandwidth limit */  /* Time a transfer started. */
 off_t limit = 0;  static struct timeval start;
   
   /* Number of bytes of current file transferred so far. */
   volatile off_t statbytes;
   
   /* Total size of current file. */
   off_t totalbytes = 0;
   
 /* Name of current file being transferred. */  /* Name of current file being transferred. */
 char *curfile;  char *curfile;
   
Line 103 
Line 120 
 char *ssh_program = _PATH_SSH_PROGRAM;  char *ssh_program = _PATH_SSH_PROGRAM;
   
 /* This is used to store the pid of ssh_program */  /* This is used to store the pid of ssh_program */
 pid_t do_cmd_pid = -1;  pid_t do_cmd_pid;
   
 static void  
 killchild(int signo)  
 {  
         if (do_cmd_pid > 1)  
                 kill(do_cmd_pid, signo);  
   
         _exit(1);  
 }  
   
 /*  /*
  * This function executes the given command as the specified user on the   * This function executes the given command as the specified user on the
  * given host.  This returns < 0 if execution fails, and >= 0 otherwise. This   * given host.  This returns < 0 if execution fails, and >= 0 otherwise. This
Line 147 
Line 155 
         close(reserved[0]);          close(reserved[0]);
         close(reserved[1]);          close(reserved[1]);
   
         /* Fork a child to execute the command on the remote host using ssh. */          /* For a child to execute the command on the remote host using ssh. */
         do_cmd_pid = fork();          do_cmd_pid = fork();
         if (do_cmd_pid == 0) {          if (do_cmd_pid == 0) {
                 /* Child. */                  /* Child. */
Line 175 
Line 183 
         *fdout = pin[1];          *fdout = pin[1];
         close(pout[1]);          close(pout[1]);
         *fdin = pout[0];          *fdin = pout[0];
         signal(SIGTERM, killchild);  
         signal(SIGINT, killchild);  
         signal(SIGHUP, killchild);  
         return 0;          return 0;
 }  }
   
Line 210 
Line 215 
 void usage(void);  void usage(void);
   
 int  int
 main(int argc, char **argv)  main(argc, argv)
           int argc;
           char *argv[];
 {  {
         int ch, fflag, tflag, status;          int ch, fflag, tflag, status;
         double speed;          char *targ;
         char *targ, *endp;  
         extern char *optarg;          extern char *optarg;
         extern int optind;          extern int optind;
   
Line 225 
Line 231 
         addargs(&args, "-oClearAllForwardings yes");          addargs(&args, "-oClearAllForwardings yes");
   
         fflag = tflag = 0;          fflag = tflag = 0;
         while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q1246S:o:F:")) != -1)          while ((ch = getopt(argc, argv, "dfprtvBCc:i:P:q46S:o:F:")) != -1)
                 switch (ch) {                  switch (ch) {
                 /* User-visible flags. */                  /* User-visible flags. */
                 case '1':  
                 case '2':  
                 case '4':                  case '4':
                 case '6':                  case '6':
                 case 'C':                  case 'C':
Line 247 
Line 251 
                 case 'B':                  case 'B':
                         addargs(&args, "-oBatchmode yes");                          addargs(&args, "-oBatchmode yes");
                         break;                          break;
                 case 'l':  
                         speed = strtod(optarg, &endp);  
                         if (speed <= 0 || *endp != '\0')  
                                 usage();  
                         limit = speed * 1024;  
                         break;  
                 case 'p':                  case 'p':
                         pflag = 1;                          pflag = 1;
                         break;                          break;
Line 289 
Line 287 
         argv += optind;          argv += optind;
   
         if ((pwd = getpwuid(userid = getuid())) == NULL)          if ((pwd = getpwuid(userid = getuid())) == NULL)
                 fatal("unknown user %u", (u_int) userid);                  fatal("unknown user %d", (int) userid);
   
         if (!isatty(STDERR_FILENO))          if (!isatty(STDERR_FILENO))
                 showprogress = 0;                  showprogress = 0;
Line 350 
Line 348 
 }  }
   
 void  void
 toremote(char *targ, int argc, char **argv)  toremote(targ, argc, argv)
           char *targ, *argv[];
           int argc;
 {  {
         int i, len;          int i, len;
         char *bp, *host, *src, *suser, *thost, *tuser;          char *bp, *host, *src, *suser, *thost, *tuser;
Line 359 
Line 359 
         if (*targ == 0)          if (*targ == 0)
                 targ = ".";                  targ = ".";
   
         if ((thost = strrchr(argv[argc - 1], '@'))) {          if ((thost = strchr(argv[argc - 1], '@'))) {
                 /* user@host */                  /* user@host */
                 *thost++ = 0;                  *thost++ = 0;
                 tuser = argv[argc - 1];                  tuser = argv[argc - 1];
                 if (*tuser == '\0')                  if (*tuser == '\0')
                         tuser = NULL;                          tuser = NULL;
                   else if (!okname(tuser))
                           exit(1);
         } else {          } else {
                 thost = argv[argc - 1];                  thost = argv[argc - 1];
                 tuser = NULL;                  tuser = NULL;
Line 378 
Line 380 
                         *src++ = 0;                          *src++ = 0;
                         if (*src == 0)                          if (*src == 0)
                                 src = ".";                                  src = ".";
                         host = strrchr(argv[i], '@');                          host = strchr(argv[i], '@');
                         len = strlen(ssh_program) + strlen(argv[i]) +                          len = strlen(ssh_program) + strlen(argv[i]) +
                             strlen(src) + (tuser ? strlen(tuser) : 0) +                              strlen(src) + (tuser ? strlen(tuser) : 0) +
                             strlen(thost) + strlen(targ) +                              strlen(thost) + strlen(targ) +
Line 390 
Line 392 
                                 suser = argv[i];                                  suser = argv[i];
                                 if (*suser == '\0')                                  if (*suser == '\0')
                                         suser = pwd->pw_name;                                          suser = pwd->pw_name;
                                 else if (!okname(suser)) {                                  else if (!okname(suser))
                                         xfree(bp);  
                                         continue;                                          continue;
                                 }  
                                 if (tuser && !okname(tuser)) {  
                                         xfree(bp);  
                                         continue;  
                                 }  
                                 snprintf(bp, len,                                  snprintf(bp, len,
                                     "%s%s %s -n "                                      "%s%s %s -n "
                                     "-l %s %s %s %s '%s%s%s:%s'",                                      "-l %s %s %s %s '%s%s%s:%s'",
Line 438 
Line 434 
 }  }
   
 void  void
 tolocal(int argc, char **argv)  tolocal(argc, argv)
           int argc;
           char *argv[];
 {  {
         int i, len;          int i, len;
         char *bp, *host, *src, *suser;          char *bp, *host, *src, *suser;
Line 461 
Line 459 
                 *src++ = 0;                  *src++ = 0;
                 if (*src == 0)                  if (*src == 0)
                         src = ".";                          src = ".";
                 if ((host = strrchr(argv[i], '@')) == NULL) {                  if ((host = strchr(argv[i], '@')) == NULL) {
                         host = argv[i];                          host = argv[i];
                         suser = NULL;                          suser = NULL;
                 } else {                  } else {
Line 469 
Line 467 
                         suser = argv[i];                          suser = argv[i];
                         if (*suser == '\0')                          if (*suser == '\0')
                                 suser = pwd->pw_name;                                  suser = pwd->pw_name;
                           else if (!okname(suser))
                                   continue;
                 }                  }
                 host = cleanhostname(host);                  host = cleanhostname(host);
                 len = strlen(src) + CMDNEEDS + 20;                  len = strlen(src) + CMDNEEDS + 20;
Line 487 
Line 487 
 }  }
   
 void  void
 source(int argc, char **argv)  source(argc, argv)
           int argc;
           char *argv[];
 {  {
         struct stat stb;          struct stat stb;
         static BUF buffer;          static BUF buffer;
         BUF *bp;          BUF *bp;
         off_t i, amt, result, statbytes;          off_t i, amt, result;
         int fd, haderr, indx;          int fd, haderr, indx;
         char *last, *name, buf[2048];          char *last, *name, buf[2048];
         int len;          int len;
Line 540 
Line 542 
                         (void) snprintf(buf, sizeof buf, "T%lu 0 %lu 0\n",                          (void) snprintf(buf, sizeof buf, "T%lu 0 %lu 0\n",
                             (u_long) stb.st_mtime,                              (u_long) stb.st_mtime,
                             (u_long) stb.st_atime);                              (u_long) stb.st_atime);
                         (void) atomicio(vwrite, remout, buf, strlen(buf));                          (void) atomicio(write, remout, buf, strlen(buf));
                         if (response() < 0)                          if (response() < 0)
                                 goto next;                                  goto next;
                 }                  }
Line 550 
Line 552 
                     (long long)stb.st_size, last);                      (long long)stb.st_size, last);
                 if (verbose_mode) {                  if (verbose_mode) {
                         fprintf(stderr, "Sending file modes: %s", buf);                          fprintf(stderr, "Sending file modes: %s", buf);
                           fflush(stderr);
                 }                  }
                 (void) atomicio(vwrite, remout, buf, strlen(buf));                  (void) atomicio(write, remout, buf, strlen(buf));
                 if (response() < 0)                  if (response() < 0)
                         goto next;                          goto next;
                 if ((bp = allocbuf(&buffer, fd, 2048)) == NULL) {                  if ((bp = allocbuf(&buffer, fd, 2048)) == NULL) {
 next:                   (void) close(fd);  next:                   (void) close(fd);
                         continue;                          continue;
                 }                  }
                 if (showprogress)                  if (showprogress) {
                         start_progress_meter(curfile, stb.st_size, &statbytes);                          totalbytes = stb.st_size;
                           progressmeter(-1);
                   }
                 /* Keep writing after an error so that we stay sync'd up. */                  /* Keep writing after an error so that we stay sync'd up. */
                 for (haderr = i = 0; i < stb.st_size; i += bp->cnt) {                  for (haderr = i = 0; i < stb.st_size; i += bp->cnt) {
                         amt = bp->cnt;                          amt = bp->cnt;
Line 571 
Line 576 
                                         haderr = result >= 0 ? EIO : errno;                                          haderr = result >= 0 ? EIO : errno;
                         }                          }
                         if (haderr)                          if (haderr)
                                 (void) atomicio(vwrite, remout, bp->buf, amt);                                  (void) atomicio(write, remout, bp->buf, amt);
                         else {                          else {
                                 result = atomicio(vwrite, remout, bp->buf, amt);                                  result = atomicio(write, remout, bp->buf, amt);
                                 if (result != amt)                                  if (result != amt)
                                         haderr = result >= 0 ? EIO : errno;                                          haderr = result >= 0 ? EIO : errno;
                                 statbytes += result;                                  statbytes += result;
                         }                          }
                         if (limit)  
                                 bwlimit(amt);  
                 }                  }
                 if (showprogress)                  if (showprogress)
                         stop_progress_meter();                          progressmeter(1);
   
                 if (close(fd) < 0 && !haderr)                  if (close(fd) < 0 && !haderr)
                         haderr = errno;                          haderr = errno;
                 if (!haderr)                  if (!haderr)
                         (void) atomicio(vwrite, remout, "", 1);                          (void) atomicio(write, remout, "", 1);
                 else                  else
                         run_err("%s: %s", name, strerror(haderr));                          run_err("%s: %s", name, strerror(haderr));
                 (void) response();                  (void) response();
Line 595 
Line 598 
 }  }
   
 void  void
 rsource(char *name, struct stat *statp)  rsource(name, statp)
           char *name;
           struct stat *statp;
 {  {
         DIR *dirp;          DIR *dirp;
         struct dirent *dp;          struct dirent *dp;
Line 614 
Line 619 
                 (void) snprintf(path, sizeof(path), "T%lu 0 %lu 0\n",                  (void) snprintf(path, sizeof(path), "T%lu 0 %lu 0\n",
                     (u_long) statp->st_mtime,                      (u_long) statp->st_mtime,
                     (u_long) statp->st_atime);                      (u_long) statp->st_atime);
                 (void) atomicio(vwrite, remout, path, strlen(path));                  (void) atomicio(write, remout, path, strlen(path));
                 if (response() < 0) {                  if (response() < 0) {
                         closedir(dirp);                          closedir(dirp);
                         return;                          return;
Line 624 
Line 629 
             (u_int) (statp->st_mode & FILEMODEMASK), 0, last);              (u_int) (statp->st_mode & FILEMODEMASK), 0, last);
         if (verbose_mode)          if (verbose_mode)
                 fprintf(stderr, "Entering directory: %s", path);                  fprintf(stderr, "Entering directory: %s", path);
         (void) atomicio(vwrite, remout, path, strlen(path));          (void) atomicio(write, remout, path, strlen(path));
         if (response() < 0) {          if (response() < 0) {
                 closedir(dirp);                  closedir(dirp);
                 return;                  return;
Line 643 
Line 648 
                 source(1, vect);                  source(1, vect);
         }          }
         (void) closedir(dirp);          (void) closedir(dirp);
         (void) atomicio(vwrite, remout, "E\n", 2);          (void) atomicio(write, remout, "E\n", 2);
         (void) response();          (void) response();
 }  }
   
 void  void
 bwlimit(int amount)  sink(argc, argv)
           int argc;
           char *argv[];
 {  {
         static struct timeval bwstart, bwend;  
         static int lamt, thresh = 16384;  
         u_int64_t wait;  
         struct timespec ts, rm;  
   
         if (!timerisset(&bwstart)) {  
                 gettimeofday(&bwstart, NULL);  
                 return;  
         }  
   
         lamt += amount;  
         if (lamt < thresh)  
                 return;  
   
         gettimeofday(&bwend, NULL);  
         timersub(&bwend, &bwstart, &bwend);  
         if (!timerisset(&bwend))  
                 return;  
   
         lamt *= 8;  
         wait = (double)1000000L * lamt / limit;  
   
         bwstart.tv_sec = wait / 1000000L;  
         bwstart.tv_usec = wait % 1000000L;  
   
         if (timercmp(&bwstart, &bwend, >)) {  
                 timersub(&bwstart, &bwend, &bwend);  
   
                 /* Adjust the wait time */  
                 if (bwend.tv_sec) {  
                         thresh /= 2;  
                         if (thresh < 2048)  
                                 thresh = 2048;  
                 } else if (bwend.tv_usec < 100) {  
                         thresh *= 2;  
                         if (thresh > 32768)  
                                 thresh = 32768;  
                 }  
   
                 TIMEVAL_TO_TIMESPEC(&bwend, &ts);  
                 while (nanosleep(&ts, &rm) == -1) {  
                         if (errno != EINTR)  
                                 break;  
                         ts = rm;  
                 }  
         }  
   
         lamt = 0;  
         gettimeofday(&bwstart, NULL);  
 }  
   
 void  
 sink(int argc, char **argv)  
 {  
         static BUF buffer;          static BUF buffer;
         struct stat stb;          struct stat stb;
         enum {          enum {
Line 712 
Line 665 
         BUF *bp;          BUF *bp;
         off_t i, j;          off_t i, j;
         int amt, count, exists, first, mask, mode, ofd, omode;          int amt, count, exists, first, mask, mode, ofd, omode;
         off_t size, statbytes;          off_t size;
         int setimes, targisdir, wrerrno = 0;          int setimes, targisdir, wrerrno = 0;
         char ch, *cp, *np, *targ, *why, *vect[1], buf[2048];          char ch, *cp, *np, *targ, *why, *vect[1], buf[2048];
         struct timeval tv[2];          struct timeval tv[2];
Line 733 
Line 686 
         if (targetshouldbedirectory)          if (targetshouldbedirectory)
                 verifydir(targ);                  verifydir(targ);
   
         (void) atomicio(vwrite, remout, "", 1);          (void) atomicio(write, remout, "", 1);
         if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode))          if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode))
                 targisdir = 1;                  targisdir = 1;
         for (first = 1;; first = 0) {          for (first = 1;; first = 0) {
Line 751 
Line 704 
   
                 if (buf[0] == '\01' || buf[0] == '\02') {                  if (buf[0] == '\01' || buf[0] == '\02') {
                         if (iamremote == 0)                          if (iamremote == 0)
                                 (void) atomicio(vwrite, STDERR_FILENO,                                  (void) atomicio(write, STDERR_FILENO,
                                     buf + 1, strlen(buf + 1));                                      buf + 1, strlen(buf + 1));
                         if (buf[0] == '\02')                          if (buf[0] == '\02')
                                 exit(1);                                  exit(1);
Line 759 
Line 712 
                         continue;                          continue;
                 }                  }
                 if (buf[0] == 'E') {                  if (buf[0] == 'E') {
                         (void) atomicio(vwrite, remout, "", 1);                          (void) atomicio(write, remout, "", 1);
                         return;                          return;
                 }                  }
                 if (ch == '\n')                  if (ch == '\n')
Line 781 
Line 734 
                         atime.tv_usec = strtol(cp, &cp, 10);                          atime.tv_usec = strtol(cp, &cp, 10);
                         if (!cp || *cp++ != '\0')                          if (!cp || *cp++ != '\0')
                                 SCREWUP("atime.usec not delimited");                                  SCREWUP("atime.usec not delimited");
                         (void) atomicio(vwrite, remout, "", 1);                          (void) atomicio(write, remout, "", 1);
                         continue;                          continue;
                 }                  }
                 if (*cp != 'C' && *cp != 'D') {                  if (*cp != 'C' && *cp != 'D') {
Line 866 
Line 819 
 bad:                    run_err("%s: %s", np, strerror(errno));  bad:                    run_err("%s: %s", np, strerror(errno));
                         continue;                          continue;
                 }                  }
                 (void) atomicio(vwrite, remout, "", 1);                  (void) atomicio(write, remout, "", 1);
                 if ((bp = allocbuf(&buffer, ofd, 4096)) == NULL) {                  if ((bp = allocbuf(&buffer, ofd, 4096)) == NULL) {
                         (void) close(ofd);                          (void) close(ofd);
                         continue;                          continue;
Line 874 
Line 827 
                 cp = bp->buf;                  cp = bp->buf;
                 wrerr = NO;                  wrerr = NO;
   
                   if (showprogress) {
                           totalbytes = size;
                           progressmeter(-1);
                   }
                 statbytes = 0;                  statbytes = 0;
                 if (showprogress)  
                         start_progress_meter(curfile, size, &statbytes);  
                 for (count = i = 0; i < size; i += 4096) {                  for (count = i = 0; i < size; i += 4096) {
                         amt = 4096;                          amt = 4096;
                         if (i + amt > size)                          if (i + amt > size)
Line 896 
Line 851 
                                 cp += j;                                  cp += j;
                                 statbytes += j;                                  statbytes += j;
                         } while (amt > 0);                          } while (amt > 0);
   
                         if (limit)  
                                 bwlimit(4096);  
   
                         if (count == bp->cnt) {                          if (count == bp->cnt) {
                                 /* Keep reading so we stay sync'd up. */                                  /* Keep reading so we stay sync'd up. */
                                 if (wrerr == NO) {                                  if (wrerr == NO) {
                                         j = atomicio(vwrite, ofd, bp->buf, count);                                          j = atomicio(write, ofd, bp->buf, count);
                                         if (j != count) {                                          if (j != count) {
                                                 wrerr = YES;                                                  wrerr = YES;
                                                 wrerrno = j >= 0 ? EIO : errno;                                                  wrerrno = j >= 0 ? EIO : errno;
Line 914 
Line 865 
                         }                          }
                 }                  }
                 if (showprogress)                  if (showprogress)
                         stop_progress_meter();                          progressmeter(1);
                 if (count != 0 && wrerr == NO &&                  if (count != 0 && wrerr == NO &&
                     (j = atomicio(vwrite, ofd, bp->buf, count)) != count) {                      (j = atomicio(write, ofd, bp->buf, count)) != count) {
                         wrerr = YES;                          wrerr = YES;
                         wrerrno = j >= 0 ? EIO : errno;                          wrerrno = j >= 0 ? EIO : errno;
                 }                  }
                 if (wrerr == NO && ftruncate(ofd, size) != 0) {                  if (ftruncate(ofd, size)) {
                         run_err("%s: truncate: %s", np, strerror(errno));                          run_err("%s: truncate: %s", np, strerror(errno));
                         wrerr = DISPLAYED;                          wrerr = DISPLAYED;
                 }                  }
Line 953 
Line 904 
                         run_err("%s: %s", np, strerror(wrerrno));                          run_err("%s: %s", np, strerror(wrerrno));
                         break;                          break;
                 case NO:                  case NO:
                         (void) atomicio(vwrite, remout, "", 1);                          (void) atomicio(write, remout, "", 1);
                         break;                          break;
                 case DISPLAYED:                  case DISPLAYED:
                         break;                          break;
Line 988 
Line 939 
                 } while (cp < &rbuf[sizeof(rbuf) - 1] && ch != '\n');                  } while (cp < &rbuf[sizeof(rbuf) - 1] && ch != '\n');
   
                 if (!iamremote)                  if (!iamremote)
                         (void) atomicio(vwrite, STDERR_FILENO, rbuf, cp - rbuf);                          (void) atomicio(write, STDERR_FILENO, rbuf, cp - rbuf);
                 ++errs;                  ++errs;
                 if (resp == 1)                  if (resp == 1)
                         return (-1);                          return (-1);
Line 1001 
Line 952 
 usage(void)  usage(void)
 {  {
         (void) fprintf(stderr,          (void) fprintf(stderr,
             "usage: scp [-pqrvBC1246] [-F config] [-S program] [-P port]\n"              "usage: scp [-pqrvBC46] [-F config] [-S program] [-P port]\n"
             "           [-c cipher] [-i identity] [-l limit] [-o option]\n"              "           [-c cipher] [-i identity] [-o option]\n"
             "           [[user@]host1:]file1 [...] [[user@]host2:]file2\n");              "           [[user@]host1:]file1 [...] [[user@]host2:]file2\n");
         exit(1);          exit(1);
 }  }
Line 1033 
Line 984 
 }  }
   
 void  void
 verifydir(char *cp)  verifydir(cp)
           char *cp;
 {  {
         struct stat stb;          struct stat stb;
   
Line 1047 
Line 999 
 }  }
   
 int  int
 okname(char *cp0)  okname(cp0)
           char *cp0;
 {  {
         int c;          int c;
         char *cp;          char *cp;
Line 1057 
Line 1010 
                 c = (int)*cp;                  c = (int)*cp;
                 if (c & 0200)                  if (c & 0200)
                         goto bad;                          goto bad;
                 if (!isalpha(c) && !isdigit(c)) {                  if (!isalpha(c) && !isdigit(c) &&
                         switch (c) {                      c != '_' && c != '-' && c != '.' && c != '+')
                         case '\'':                          goto bad;
                         case '"':  
                         case '`':  
                         case ' ':  
                         case '#':  
                                 goto bad;  
                         default:  
                                 break;  
                         }  
                 }  
         } while (*++cp);          } while (*++cp);
         return (1);          return (1);
   
Line 1077 
Line 1021 
 }  }
   
 BUF *  BUF *
 allocbuf(BUF *bp, int fd, int blksize)  allocbuf(bp, fd, blksize)
           BUF *bp;
           int fd, blksize;
 {  {
         size_t size;          size_t size;
         struct stat stb;          struct stat stb;
Line 1086 
Line 1032 
                 run_err("fstat: %s", strerror(errno));                  run_err("fstat: %s", strerror(errno));
                 return (0);                  return (0);
         }          }
         size = roundup(stb.st_blksize, blksize);          if (stb.st_blksize == 0)
         if (size == 0)  
                 size = blksize;                  size = blksize;
           else
                   size = blksize + (stb.st_blksize - blksize % stb.st_blksize) %
                       stb.st_blksize;
         if (bp->cnt >= size)          if (bp->cnt >= size)
                 return (bp);                  return (bp);
         if (bp->buf == NULL)          if (bp->buf == NULL)
Line 1101 
Line 1049 
 }  }
   
 void  void
 lostconn(int signo)  lostconn(signo)
           int signo;
 {  {
         if (!iamremote)          if (!iamremote)
                 write(STDERR_FILENO, "lost connection\n", 16);                  write(STDERR_FILENO, "lost connection\n", 16);
Line 1109 
Line 1058 
                 _exit(1);                  _exit(1);
         else          else
                 exit(1);                  exit(1);
   }
   
   static void
   updateprogressmeter(int ignore)
   {
           int save_errno = errno;
   
           progressmeter(0);
           signal(SIGALRM, updateprogressmeter);
           alarm(PROGRESSTIME);
           errno = save_errno;
   }
   
   static int
   foregroundproc(void)
   {
           static pid_t pgrp = -1;
           int ctty_pgrp;
   
           if (pgrp == -1)
                   pgrp = getpgrp();
   
           return ((ioctl(STDOUT_FILENO, TIOCGPGRP, &ctty_pgrp) != -1 &&
                    ctty_pgrp == pgrp));
   }
   
   void
   progressmeter(int flag)
   {
           static const char prefixes[] = " KMGTP";
           static struct timeval lastupdate;
           static off_t lastsize;
           struct timeval now, td, wait;
           off_t cursize, abbrevsize;
           double elapsed;
           int ratio, barlength, i, remaining;
           char buf[512];
   
           if (flag == -1) {
                   (void) gettimeofday(&start, (struct timezone *) 0);
                   lastupdate = start;
                   lastsize = 0;
           }
           if (foregroundproc() == 0)
                   return;
   
           (void) gettimeofday(&now, (struct timezone *) 0);
           cursize = statbytes;
           if (totalbytes != 0) {
                   ratio = 100.0 * cursize / totalbytes;
                   ratio = MAX(ratio, 0);
                   ratio = MIN(ratio, 100);
           } else
                   ratio = 100;
   
           snprintf(buf, sizeof(buf), "\r%-20.20s %3d%% ", curfile, ratio);
   
           barlength = getttywidth() - 51;
           if (barlength > 0) {
                   i = barlength * ratio / 100;
                   snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
                       "|%.*s%*s|", i,
                       "*******************************************************"
                       "*******************************************************"
                       "*******************************************************"
                       "*******************************************************"
                       "*******************************************************"
                       "*******************************************************"
                       "*******************************************************",
                       barlength - i, "");
           }
           i = 0;
           abbrevsize = cursize;
           while (abbrevsize >= 100000 && i < sizeof(prefixes)) {
                   i++;
                   abbrevsize >>= 10;
           }
           snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %5llu %c%c ",
               (unsigned long long) abbrevsize, prefixes[i],
               prefixes[i] == ' ' ? ' ' : 'B');
   
           timersub(&now, &lastupdate, &wait);
           if (cursize > lastsize) {
                   lastupdate = now;
                   lastsize = cursize;
                   if (wait.tv_sec >= STALLTIME) {
                           start.tv_sec += wait.tv_sec;
                           start.tv_usec += wait.tv_usec;
                   }
                   wait.tv_sec = 0;
           }
           timersub(&now, &start, &td);
           elapsed = td.tv_sec + (td.tv_usec / 1000000.0);
   
           if (flag != 1 &&
               (statbytes <= 0 || elapsed <= 0.0 || cursize > totalbytes)) {
                   snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
                       "   --:-- ETA");
           } else if (wait.tv_sec >= STALLTIME) {
                   snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
                       " - stalled -");
           } else {
                   if (flag != 1)
                           remaining = (int)(totalbytes / (statbytes / elapsed) -
                               elapsed);
                   else
                           remaining = elapsed;
   
                   i = remaining / 3600;
                   if (i)
                           snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
                               "%2d:", i);
                   else
                           snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
                               "   ");
                   i = remaining % 3600;
                   snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
                       "%02d:%02d%s", i / 60, i % 60,
                       (flag != 1) ? " ETA" : "    ");
           }
           atomicio(write, fileno(stdout), buf, strlen(buf));
   
           if (flag == -1) {
                   signal(SIGALRM, updateprogressmeter);
                   alarm(PROGRESSTIME);
           } else if (flag == 1) {
                   alarm(0);
                   atomicio(write, fileno(stdout), "\n", 1);
                   statbytes = 0;
           }
   }
   
   int
   getttywidth(void)
   {
           struct winsize winsize;
   
           if (ioctl(fileno(stdout), TIOCGWINSZ, &winsize) != -1)
                   return (winsize.ws_col ? winsize.ws_col : 80);
           else
                   return (80);
 }  }

Legend:
Removed from v.1.91.2.2  
changed lines
  Added in v.1.92