[BACK]Return to ftpcmd.y CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / libexec / ftpd

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/libexec/ftpd/ftpcmd.y between version 1.48.2.2 and 1.72

version 1.48.2.2, 2001/03/29 14:14:17 version 1.72, 2002/11/29 14:39:59
Line 1 
Line 1 
 /*      $NetBSD$        */  /*      $NetBSD$        */
   
 /*-  /*-
  * Copyright (c) 1997-2000 The NetBSD Foundation, Inc.   * Copyright (c) 1997-2002 The NetBSD Foundation, Inc.
  * All rights reserved.   * All rights reserved.
  *   *
  * This code is derived from software contributed to The NetBSD Foundation   * This code is derived from software contributed to The NetBSD Foundation
Line 97  __RCSID("$NetBSD$");
Line 97  __RCSID("$NetBSD$");
   
 #include <ctype.h>  #include <ctype.h>
 #include <errno.h>  #include <errno.h>
 #include <glob.h>  
 #include <pwd.h>  #include <pwd.h>
 #include <setjmp.h>  #include <setjmp.h>
 #include <signal.h>  #include <signal.h>
Line 121  static int cmd_type;
Line 120  static int cmd_type;
 static  int cmd_form;  static  int cmd_form;
 static  int cmd_bytesz;  static  int cmd_bytesz;
   
 char    cbuf[512];  char    cbuf[FTP_BUFLEN];
   char    *cmdp;
 char    *fromname;  char    *fromname;
   
 %}  %}
   
 %union {  %union {
         int     i;          struct {
                   off_t   o;
                   int     i;
           } u;
         char   *s;          char   *s;
 }  }
   
Line 162  char *fromname;
Line 165  char *fromname;
   
 %token  <s> STRING  %token  <s> STRING
 %token  <s> ALL  %token  <s> ALL
 %token  <i> NUMBER  %token  <u> NUMBER
   
 %type   <i> check_login octal_number byte_size  %type   <u.i> check_login octal_number byte_size
 %type   <i> struct_code mode_code type_code form_code decimal_integer  %type   <u.i> struct_code mode_code type_code form_code decimal_integer
 %type   <s> pathstring pathname password username  %type   <s> pathstring pathname password username
 %type   <s> mechanism_name base64data prot_code  %type   <s> mechanism_name base64data prot_code
   
 %start  cmd_list  %start  cmd_sel
   
 %%  %%
   
 cmd_list  cmd_sel
         : /* empty */          : cmd
   
         | cmd_list cmd  
                 {                  {
                         fromname = NULL;                          fromname = NULL;
                         restart_point = (off_t) 0;                          restart_point = (off_t) 0;
                 }                  }
   
         | cmd_list rcmd          | rcmd
   
         ;          ;
   
Line 295  cmd
Line 296  cmd
         | LPSV check_login CRLF          | LPSV check_login CRLF
                 {                  {
                         if ($2) {                          if ($2) {
                                 if (epsvall)                                  if (CURCLASS_FLAGS_ISSET(passive)) {
                                         reply(501,                                          if (epsvall)
                                             "LPSV disallowed after EPSV ALL");                                                  reply(501,
                                 else                                                      "LPSV disallowed after EPSV ALL");
                                         long_passive("LPSV", PF_UNSPEC);                                          else
                                                   long_passive("LPSV", PF_UNSPEC);
                                   } else
                                           reply(500, "LPSV mode not available.");
                         }                          }
                 }                  }
   
         | EPSV check_login SP NUMBER CRLF          | EPSV check_login SP NUMBER CRLF
                 {                  {
                         if ($2)                          if ($2) {
                                 long_passive("EPSV", epsvproto2af($4));                                  if (CURCLASS_FLAGS_ISSET(passive))
                                           long_passive("EPSV",
                                               epsvproto2af($4.i));
                                   else
                                           reply(500, "EPSV mode not available.");
                           }
                 }                  }
   
         | EPSV check_login SP ALL CRLF          | EPSV check_login SP ALL CRLF
                 {                  {
                         if ($2) {                          if ($2) {
                                 reply(200, "EPSV ALL command successful.");                                  if (CURCLASS_FLAGS_ISSET(passive)) {
                                 epsvall++;                                          reply(200,
                                               "EPSV ALL command successful.");
                                           epsvall++;
                                   } else
                                           reply(500, "EPSV mode not available.");
                         }                          }
                 }                  }
   
         | EPSV check_login CRLF          | EPSV check_login CRLF
                 {                  {
                         if ($2)                          if ($2) {
                                 long_passive("EPSV", PF_UNSPEC);                                  if (CURCLASS_FLAGS_ISSET(passive))
                                           long_passive("EPSV", PF_UNSPEC);
                                   else
                                           reply(500, "EPSV mode not available.");
                           }
                 }                  }
   
         | TYPE check_login SP type_code CRLF          | TYPE check_login SP type_code CRLF
Line 454  cmd
Line 471  cmd
   
         | ABOR check_login CRLF          | ABOR check_login CRLF
                 {                  {
                         if ($2)                          if (is_oob)
                                   abor();
                           else if ($2)
                                 reply(225, "ABOR command successful.");                                  reply(225, "ABOR command successful.");
                 }                  }
   
Line 551  cmd
Line 570  cmd
                 {                  {
                         if ($4) {                          if ($4) {
                                 reply(200,                                  reply(200,
                             "Current IDLE time limit is %d seconds; max %d",                                      "Current IDLE time limit is " LLF
                                     curclass.timeout, curclass.maxtimeout);                                      " seconds; max " LLF,
                                       (LLT)curclass.timeout,
                                       (LLT)curclass.maxtimeout);
                         }                          }
                 }                  }
   
         | SITE SP IDLE check_login SP NUMBER CRLF          | SITE SP IDLE check_login SP NUMBER CRLF
                 {                  {
                         if ($4) {                          if ($4) {
                                 if ($6 < 30 || $6 > curclass.maxtimeout) {                                  if ($6.i < 30 || $6.i > curclass.maxtimeout) {
                                         reply(501,                                          reply(501,
                             "IDLE time limit must be between 30 and %d seconds",                                  "IDLE time limit must be between 30 and "
                                             curclass.maxtimeout);                                              LLF " seconds",
                                               (LLT)curclass.maxtimeout);
                                 } else {                                  } else {
                                         curclass.timeout = $6;                                          curclass.timeout = $6.i;
                                         (void) alarm(curclass.timeout);                                          (void) alarm(curclass.timeout);
                                         reply(200,                                          reply(200,
                                             "IDLE time limit set to %d seconds",                                              "IDLE time limit set to "
                                             curclass.timeout);                                              LLF " seconds",
                                               (LLT)curclass.timeout);
                                 }                                  }
                         }                          }
                 }                  }
Line 584  cmd
Line 607  cmd
   
         | SITE SP RATEGET check_login SP STRING CRLF          | SITE SP RATEGET check_login SP STRING CRLF
                 {                  {
                           char errbuf[100];
                         char *p = $6;                          char *p = $6;
                         LLT rate;                          LLT rate;
   
                         if ($4) {                          if ($4) {
                                 rate = strsuftoll(p);                                  rate = strsuftollx("RATEGET", p, 0,
                                 if (rate == -1)                                      curclass.maxrateget
                                         reply(501, "Invalid RATEGET %s", p);                                      ? curclass.maxrateget
                                 else if (curclass.maxrateget &&                                      : LLTMAX, errbuf, sizeof(errbuf));
                                     rate > curclass.maxrateget)                                  if (errbuf[0])
                                         reply(501,                                          reply(501, "%s", errbuf);
                         "RATEGET " LLF " is larger than maximum RATEGET " LLF,  
                                             (LLT)rate,  
                                             (LLT)curclass.maxrateget);  
                                 else {                                  else {
                                         curclass.rateget = rate;                                          curclass.rateget = rate;
                                         reply(200,                                          reply(200,
Line 618  cmd
Line 639  cmd
   
         | SITE SP RATEPUT check_login SP STRING CRLF          | SITE SP RATEPUT check_login SP STRING CRLF
                 {                  {
                           char errbuf[100];
                         char *p = $6;                          char *p = $6;
                         LLT rate;                          LLT rate;
   
                         if ($4) {                          if ($4) {
                                 rate = strsuftoll(p);                                  rate = strsuftollx("RATEPUT", p, 0,
                                 if (rate == -1)                                      curclass.maxrateput
                                         reply(501, "Invalid RATEPUT %s", p);                                      ? curclass.maxrateput
                                 else if (curclass.maxrateput &&                                      : LLTMAX, errbuf, sizeof(errbuf));
                                     rate > curclass.maxrateput)                                  if (errbuf[0])
                                         reply(501,                                          reply(501, "%s", errbuf);
                         "RATEPUT " LLF " is larger than maximum RATEPUT " LLF,  
                                             (LLT)rate,  
                                             (LLT)curclass.maxrateput);  
                                 else {                                  else {
                                         curclass.rateput = rate;                                          curclass.rateput = rate;
                                         reply(200,                                          reply(200,
Line 656  cmd
Line 675  cmd
                 {                  {
                         int oldmask;                          int oldmask;
   
                         if ($4 && CURCLASS_FLAGS_ISSET(modify)) {                          if ($4 && check_write("", 0)) {
                                 if (($6 == -1) || ($6 > 0777)) {                                  if (($6 == -1) || ($6 > 0777)) {
                                         reply(501, "Bad UMASK value");                                          reply(501, "Bad UMASK value");
                                 } else {                                  } else {
Line 687  cmd
Line 706  cmd
   
         | STAT CRLF          | STAT CRLF
                 {                  {
                         statcmd();                          if (is_oob)
                                   statxfer();
                           else
                                   statcmd();
                 }                  }
   
         | HELP CRLF          | HELP CRLF
Line 858  cmd
Line 880  cmd
         ;          ;
   
 rcmd  rcmd
         : REST check_login SP byte_size CRLF          : REST check_login SP NUMBER CRLF
                 {                  {
                         if ($2) {                          if ($2) {
                                 fromname = NULL;                                  fromname = NULL;
                                 restart_point = $4; /* XXX: $4 is only "int" */                                  restart_point = $4.o;
                                 reply(350,                                  reply(350,
     "Restarting at " LLF ". Send STORE or RETRIEVE to initiate transfer.",      "Restarting at " LLF ". Send STORE or RETRIEVE to initiate transfer.",
                                     (LLT)restart_point);                                      (LLT)restart_point);
Line 894  password
Line 916  password
   
 byte_size  byte_size
         : NUMBER          : NUMBER
                   {
                           $$ = $1.i;
                   }
         ;          ;
   
 host_port  host_port
Line 906  host_port
Line 931  host_port
                         data_dest.su_len = sizeof(struct sockaddr_in);                          data_dest.su_len = sizeof(struct sockaddr_in);
                         data_dest.su_family = AF_INET;                          data_dest.su_family = AF_INET;
                         p = (char *)&data_dest.su_port;                          p = (char *)&data_dest.su_port;
                         p[0] = $9; p[1] = $11;                          p[0] = $9.i; p[1] = $11.i;
                         a = (char *)&data_dest.su_addr;                          a = (char *)&data_dest.su_addr;
                         a[0] = $1; a[1] = $3; a[2] = $5; a[3] = $7;                          a[0] = $1.i; a[1] = $3.i; a[2] = $5.i; a[3] = $7.i;
                 }                  }
         ;          ;
   
Line 923  host_long_port4
Line 948  host_long_port4
                         data_dest.su_len = sizeof(struct sockaddr_in);                          data_dest.su_len = sizeof(struct sockaddr_in);
                         data_dest.su_family = AF_INET;                          data_dest.su_family = AF_INET;
                         p = (char *)&data_dest.su_port;                          p = (char *)&data_dest.su_port;
                         p[0] = $15; p[1] = $17;                          p[0] = $15.i; p[1] = $17.i;
                         a = (char *)&data_dest.su_addr;                          a = (char *)&data_dest.su_addr;
                         a[0] =  $5;  a[1] =  $7;  a[2] =  $9;  a[3] = $11;                          a[0] = $5.i; a[1] = $7.i; a[2] = $9.i; a[3] = $11.i;
   
                         /* reject invalid LPRT command */                          /* reject invalid LPRT command */
                         if ($1 != 4 || $3 != 4 || $13 != 2)                          if ($1.i != 4 || $3.i != 4 || $13.i != 2)
                                 memset(&data_dest, 0, sizeof(data_dest));                                  memset(&data_dest, 0, sizeof(data_dest));
                 }                  }
         ;          ;
Line 948  host_long_port6
Line 973  host_long_port6
                         data_dest.su_len = sizeof(struct sockaddr_in6);                          data_dest.su_len = sizeof(struct sockaddr_in6);
                         data_dest.su_family = AF_INET6;                          data_dest.su_family = AF_INET6;
                         p = (char *)&data_dest.su_port;                          p = (char *)&data_dest.su_port;
                         p[0] = $39; p[1] = $41;                          p[0] = $39.i; p[1] = $41.i;
                         a = (char *)&data_dest.si_su.su_sin6.sin6_addr;                          a = (char *)&data_dest.si_su.su_sin6.sin6_addr;
                          a[0] =  $5;  a[1] =  $7;  a[2] =  $9;  a[3] = $11;                          a[0] = $5.i; a[1] = $7.i; a[2] = $9.i; a[3] = $11.i;
                          a[4] = $13;  a[5] = $15;  a[6] = $17;  a[7] = $19;                          a[4] = $13.i; a[5] = $15.i; a[6] = $17.i; a[7] = $19.i;
                          a[8] = $21;  a[9] = $23; a[10] = $25; a[11] = $27;                          a[8] = $21.i; a[9] = $23.i; a[10] = $25.i; a[11] = $27.i;
                         a[12] = $29; a[13] = $31; a[14] = $33; a[15] = $35;                          a[12] = $29.i; a[13] = $31.i; a[14] = $33.i; a[15] = $35.i;
                         if (his_addr.su_family == AF_INET6) {                          if (his_addr.su_family == AF_INET6) {
                                 /* XXX: more sanity checks! */                                  /* XXX: more sanity checks! */
                                 data_dest.su_scope_id = his_addr.su_scope_id;                                  data_dest.su_scope_id = his_addr.su_scope_id;
Line 962  host_long_port6
Line 987  host_long_port6
                         memset(&data_dest, 0, sizeof(data_dest));                          memset(&data_dest, 0, sizeof(data_dest));
 #endif /* INET6 */  #endif /* INET6 */
                         /* reject invalid LPRT command */                          /* reject invalid LPRT command */
                         if ($1 != 6 || $3 != 16 || $37 != 2)                          if ($1.i != 6.i || $3.i != 16.i || $37.i != 2)
                                 memset(&data_dest, 0, sizeof(data_dest));                                  memset(&data_dest, 0, sizeof(data_dest));
                 }                  }
         ;          ;
Line 1078  pathname
Line 1103  pathname
                          * others.                           * others.
                          */                           */
                         if (logged_in && $1 && *$1 == '~') {                          if (logged_in && $1 && *$1 == '~') {
                                 glob_t gl;                                  char    *path, *home, *result;
                                 int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_TILDE;                                  size_t  len;
   
                                   path = strchr($1 + 1, '/');
                                   if (path != NULL)
                                           *path++ = '\0';
                                 if ($1[1] == '\0')                                  if ($1[1] == '\0')
                                         $$ = xstrdup(homedir);                                          home = homedir;
                                 else {                                  else {
                                         memset(&gl, 0, sizeof(gl));                                          struct passwd   *hpw;
                                         if (glob($1, flags, NULL, &gl) ||  
                                             gl.gl_pathc == 0) {                                          if ((hpw = getpwnam($1 + 1)) != NULL)
                                                 reply(550, "not found");                                                  home = hpw->pw_dir;
                                                 $$ = NULL;                                          else
                                         } else                                                  home = $1;
                                                 $$ = xstrdup(gl.gl_pathv[0]);  
                                         globfree(&gl);  
                                 }                                  }
                                   len = strlen(home) + 1;
                                   if (path != NULL)
                                           len += strlen(path) + 1;
                                   if ((result = malloc(len)) == NULL)
                                           fatal("Local resource failure: malloc");
                                   strlcpy(result, home, len);
                                   if (path != NULL) {
                                           strlcat(result, "/", len);
                                           strlcat(result, path, len);
                                   }
                                   $$ = result;
                                 free($1);                                  free($1);
                         } else                          } else
                                 $$ = $1;                                  $$ = $1;
Line 1112  octal_number
Line 1149  octal_number
                          * Convert a number that was read as decimal number                           * Convert a number that was read as decimal number
                          * to what it would be if it had been read as octal.                           * to what it would be if it had been read as octal.
                          */                           */
                         dec = $1;                          dec = $1.i;
                         multby = 1;                          multby = 1;
                         ret = 0;                          ret = 0;
                         while (dec) {                          while (dec) {
Line 1143  prot_code
Line 1180  prot_code
   
 decimal_integer  decimal_integer
         : NUMBER          : NUMBER
                   {
                           $$ = $1.i;
                   }
         ;          ;
   
 check_login  check_login
Line 1170  check_login
Line 1210  check_login
 #define SITECMD 7       /* SITE command */  #define SITECMD 7       /* SITE command */
 #define NSTR    8       /* Number followed by a string */  #define NSTR    8       /* Number followed by a string */
 #define NOARGS  9       /* No arguments allowed */  #define NOARGS  9       /* No arguments allowed */
   #define EOLN    10      /* End of line */
   
 struct tab cmdtab[] = {  struct tab cmdtab[] = {
                                 /* From RFC 959, in order defined (5.3.1) */                                  /* From RFC 959, in order defined (5.3.1) */
Line 1198  struct tab cmdtab[] = {
Line 1239  struct tab cmdtab[] = {
         { "REST", REST, ARGS,   1,      "<sp> offset (restart command)" },          { "REST", REST, ARGS,   1,      "<sp> offset (restart command)" },
         { "RNFR", RNFR, STR1,   1,      "<sp> file-name" },          { "RNFR", RNFR, STR1,   1,      "<sp> file-name" },
         { "RNTO", RNTO, STR1,   1,      "<sp> file-name" },          { "RNTO", RNTO, STR1,   1,      "<sp> file-name" },
         { "ABOR", ABOR, NOARGS, 1,      "(abort operation)" },          { "ABOR", ABOR, NOARGS, 4,      "(abort operation)" },
         { "DELE", DELE, STR1,   1,      "<sp> file-name" },          { "DELE", DELE, STR1,   1,      "<sp> file-name" },
         { "RMD",  RMD,  STR1,   1,      "<sp> path-name" },          { "RMD",  RMD,  STR1,   1,      "<sp> path-name" },
         { "MKD",  MKD,  STR1,   1,      "<sp> path-name" },          { "MKD",  MKD,  STR1,   1,      "<sp> path-name" },
Line 1207  struct tab cmdtab[] = {
Line 1248  struct tab cmdtab[] = {
         { "NLST", NLST, OSTR,   1,      "[ <sp> path-name ]" },          { "NLST", NLST, OSTR,   1,      "[ <sp> path-name ]" },
         { "SITE", SITE, SITECMD, 1,     "site-cmd [ <sp> arguments ]" },          { "SITE", SITE, SITECMD, 1,     "site-cmd [ <sp> arguments ]" },
         { "SYST", SYST, NOARGS, 1,      "(get type of operating system)" },          { "SYST", SYST, NOARGS, 1,      "(get type of operating system)" },
         { "STAT", STAT, OSTR,   1,      "[ <sp> path-name ]" },          { "STAT", STAT, OSTR,   4,      "[ <sp> path-name ]" },
         { "HELP", HELP, OSTR,   1,      "[ <sp> <string> ]" },          { "HELP", HELP, OSTR,   1,      "[ <sp> <string> ]" },
         { "NOOP", NOOP, NOARGS, 2,      "" },          { "NOOP", NOOP, NOARGS, 2,      "" },
   
Line 1217  struct tab cmdtab[] = {
Line 1258  struct tab cmdtab[] = {
         { "PROT", PROT, STR1,   1,      "<sp> prot-code" },          { "PROT", PROT, STR1,   1,      "<sp> prot-code" },
         { "PBSZ", PBSZ, ARGS,   1,      "<sp> decimal-integer" },          { "PBSZ", PBSZ, ARGS,   1,      "<sp> decimal-integer" },
         { "CCC",  CCC,  NOARGS, 1,      "(Disable data protection)" },          { "CCC",  CCC,  NOARGS, 1,      "(Disable data protection)" },
         { "MIC",  MIC,  STR1,   1,      "<sp> base64data" },          { "MIC",  MIC,  STR1,   4,      "<sp> base64data" },
         { "CONF", CONF, STR1,   1,      "<sp> base64data" },          { "CONF", CONF, STR1,   4,      "<sp> base64data" },
         { "ENC",  ENC,  STR1,   1,      "<sp> base64data" },          { "ENC",  ENC,  STR1,   4,      "<sp> base64data" },
   
                                 /* From RFC 2389, in order defined */                                  /* From RFC 2389, in order defined */
         { "FEAT", FEAT, NOARGS, 1,      "(display extended features)" },          { "FEAT", FEAT, NOARGS, 1,      "(display extended features)" },
Line 1249  struct tab cmdtab[] = {
Line 1290  struct tab cmdtab[] = {
 };  };
   
 struct tab sitetab[] = {  struct tab sitetab[] = {
         { "CHMOD",      CHMOD,  NSTR, 1,        "<sp> mode <sp> file-name" },          { "CHMOD",      CHMOD,  NSTR,   1,      "<sp> mode <sp> file-name" },
         { "HELP",       HELP,   OSTR, 1,        "[ <sp> <string> ]" },          { "HELP",       HELP,   OSTR,   1,      "[ <sp> <string> ]" },
         { "IDLE",       IDLE,   ARGS, 1,        "[ <sp> maximum-idle-time ]" },          { "IDLE",       IDLE,   ARGS,   1,      "[ <sp> maximum-idle-time ]" },
         { "RATEGET",    RATEGET,OSTR, 1,        "[ <sp> get-throttle-rate ]" },          { "RATEGET",    RATEGET,OSTR,   1,      "[ <sp> get-throttle-rate ]" },
         { "RATEPUT",    RATEPUT,OSTR, 1,        "[ <sp> put-throttle-rate ]" },          { "RATEPUT",    RATEPUT,OSTR,   1,      "[ <sp> put-throttle-rate ]" },
         { "UMASK",      UMASK,  ARGS, 1,        "[ <sp> umask ]" },          { "UMASK",      UMASK,  ARGS,   1,      "[ <sp> umask ]" },
         { NULL,         0,     0,     0,        NULL }          { NULL,         0,      0,      0,      NULL }
 };  };
   
 static  int     check_write(const char *, int);  static  int     check_write(const char *, int);
Line 1269  extern int epsvall;
Line 1310  extern int epsvall;
 /*  /*
  * Check if a filename is allowed to be modified (isupload == 0) or   * Check if a filename is allowed to be modified (isupload == 0) or
  * uploaded (isupload == 1), and if necessary, check the filename is `sane'.   * uploaded (isupload == 1), and if necessary, check the filename is `sane'.
    * If the filename is NULL, fail.
    * If the filename is "", don't do the sane name check.
  */   */
 static int  static int
 check_write(const char *file, int isupload)  check_write(const char *file, int isupload)
Line 1289  check_write(const char *file, int isuplo
Line 1332  check_write(const char *file, int isuplo
                 reply(502, "No permission to use this command.");                  reply(502, "No permission to use this command.");
                 return (0);                  return (0);
         }          }
   
                 /* checking sanenames */                  /* checking sanenames */
         if (CURCLASS_FLAGS_ISSET(sanenames)) {          if (file[0] != '\0' && CURCLASS_FLAGS_ISSET(sanenames)) {
                 const char *p;                  const char *p;
   
                 if (file[0] == '.')                  if (file[0] == '.')
Line 1410  toolong(int signo)
Line 1454  toolong(int signo)
 {  {
   
         reply(421,          reply(421,
             "Timeout (%d seconds): closing control connection.",              "Timeout (" LLF " seconds): closing control connection.",
             curclass.timeout);              (LLT)curclass.timeout);
         if (logging)          if (logging)
                 syslog(LOG_INFO, "User %s timed out after %d seconds",                  syslog(LOG_INFO, "User %s timed out after " LLF " seconds",
                     (pw ? pw->pw_name : "unknown"), curclass.timeout);                      (pw ? pw->pw_name : "unknown"), (LLT)curclass.timeout);
         dologout(1);          dologout(1);
 }  }
   
   void
   ftp_handle_line(char *cp)
   {
   
           cmdp = cp;
           yyparse();
   }
   
   void
   ftp_loop(void)
   {
   
           while (1) {
                   (void) signal(SIGALRM, toolong);
                   (void) alarm(curclass.timeout);
                   if (getline(cbuf, sizeof(cbuf)-1, stdin) == NULL) {
                           reply(221, "You could at least say goodbye.");
                           dologout(0);
                   }
                   (void) alarm(0);
                   ftp_handle_line(cbuf);
           }
           /*NOTREACHED*/
   }
   
 static int  static int
 yylex(void)  yylex(void)
 {  {
Line 1431  yylex(void)
Line 1500  yylex(void)
   
         case CMD:          case CMD:
                 hasyyerrored = 0;                  hasyyerrored = 0;
                 (void) signal(SIGALRM, toolong);                  if ((cp = strchr(cmdp, '\r'))) {
                 (void) alarm(curclass.timeout);  
                 if (getline(cbuf, sizeof(cbuf)-1, stdin) == NULL) {  
                         reply(221, "You could at least say goodbye.");  
                         dologout(0);  
                 }  
                 (void) alarm(0);  
                 if ((cp = strchr(cbuf, '\r'))) {  
                         *cp = '\0';                          *cp = '\0';
 #if HAVE_SETPROCTITLE  #if HAVE_SETPROCTITLE
                         if (strncasecmp(cbuf, "PASS", 4) != 0 &&                          if (strncasecmp(cmdp, "PASS", 4) != 0 &&
                             strncasecmp(cbuf, "ACCT", 4) != 0)                              strncasecmp(cmdp, "ACCT", 4) != 0)
                                 setproctitle("%s: %s", proctitle, cbuf);                                  setproctitle("%s: %s", proctitle, cmdp);
 #endif /* HAVE_SETPROCTITLE */  #endif /* HAVE_SETPROCTITLE */
                         *cp++ = '\n';                          *cp++ = '\n';
                         *cp = '\0';                          *cp = '\0';
                 }                  }
                 if ((cp = strpbrk(cbuf, " \n")))                  if ((cp = strpbrk(cmdp, " \n")))
                         cpos = cp - cbuf;                          cpos = cp - cmdp;
                 if (cpos == 0)                  if (cpos == 0)
                         cpos = 4;                          cpos = 4;
                 c = cbuf[cpos];                  c = cmdp[cpos];
                 cbuf[cpos] = '\0';                  cmdp[cpos] = '\0';
                 p = lookup(cmdtab, cbuf);                  p = lookup(cmdtab, cmdp);
                 cbuf[cpos] = c;                  cmdp[cpos] = c;
                 if (p != NULL) {                  if (p != NULL) {
                         if (! CMD_IMPLEMENTED(p)) {                          if (is_oob && ! CMD_OOB(p)) {
                                   /* command will be handled in-band */
                                   return (0);
                           } else if (! CMD_IMPLEMENTED(p)) {
                                 reply(502, "%s command not implemented.",                                  reply(502, "%s command not implemented.",
                                     p->name);                                      p->name);
                                 hasyyerrored = 1;                                  hasyyerrored = 1;
Line 1470  yylex(void)
Line 1535  yylex(void)
                 break;                  break;
   
         case SITECMD:          case SITECMD:
                 if (cbuf[cpos] == ' ') {                  if (cmdp[cpos] == ' ') {
                         cpos++;                          cpos++;
                         return (SP);                          return (SP);
                 }                  }
                 cp = &cbuf[cpos];                  cp = &cmdp[cpos];
                 if ((cp2 = strpbrk(cp, " \n")))                  if ((cp2 = strpbrk(cp, " \n")))
                         cpos = cp2 - cbuf;                          cpos = cp2 - cmdp;
                 c = cbuf[cpos];                  c = cmdp[cpos];
                 cbuf[cpos] = '\0';                  cmdp[cpos] = '\0';
                 p = lookup(sitetab, cp);                  p = lookup(sitetab, cp);
                 cbuf[cpos] = c;                  cmdp[cpos] = c;
                 if (p != NULL) {                  if (p != NULL) {
                         if (!CMD_IMPLEMENTED(p)) {                          if (!CMD_IMPLEMENTED(p)) {
                                 reply(502, "SITE %s command not implemented.",                                  reply(502, "SITE %s command not implemented.",
Line 1495  yylex(void)
Line 1560  yylex(void)
                 break;                  break;
   
         case OSTR:          case OSTR:
                 if (cbuf[cpos] == '\n') {                  if (cmdp[cpos] == '\n') {
                         state = CMD;                          state = EOLN;
                         return (CRLF);                          return (CRLF);
                 }                  }
                 /* FALLTHROUGH */                  /* FALLTHROUGH */
Line 1504  yylex(void)
Line 1569  yylex(void)
         case STR1:          case STR1:
         case ZSTR1:          case ZSTR1:
         dostr1:          dostr1:
                 if (cbuf[cpos] == ' ') {                  if (cmdp[cpos] == ' ') {
                         cpos++;                          cpos++;
                         state = state == OSTR ? STR2 : state+1;                          state = state == OSTR ? STR2 : state+1;
                         return (SP);                          return (SP);
Line 1512  yylex(void)
Line 1577  yylex(void)
                 break;                  break;
   
         case ZSTR2:          case ZSTR2:
                 if (cbuf[cpos] == '\n') {                  if (cmdp[cpos] == '\n') {
                         state = CMD;                          state = EOLN;
                         return (CRLF);                          return (CRLF);
                 }                  }
                 /* FALLTHROUGH */                  /* FALLTHROUGH */
   
         case STR2:          case STR2:
                 cp = &cbuf[cpos];                  cp = &cmdp[cpos];
                 n = strlen(cp);                  n = strlen(cp);
                 cpos += n - 1;                  cpos += n - 1;
                 /*                  /*
                  * Make sure the string is nonempty and \n terminated.                   * Make sure the string is nonempty and \n terminated.
                  */                   */
                 if (n > 1 && cbuf[cpos] == '\n') {                  if (n > 1 && cmdp[cpos] == '\n') {
                         cbuf[cpos] = '\0';                          cmdp[cpos] = '\0';
                         yylval.s = xstrdup(cp);                          yylval.s = xstrdup(cp);
                         cbuf[cpos] = '\n';                          cmdp[cpos] = '\n';
                         state = ARGS;                          state = ARGS;
                         return (STRING);                          return (STRING);
                 }                  }
                 break;                  break;
   
         case NSTR:          case NSTR:
                 if (cbuf[cpos] == ' ') {                  if (cmdp[cpos] == ' ') {
                         cpos++;                          cpos++;
                         return (SP);                          return (SP);
                 }                  }
                 if (isdigit(cbuf[cpos])) {                  if (isdigit(cmdp[cpos])) {
                         cp = &cbuf[cpos];                          cp = &cmdp[cpos];
                         while (isdigit(cbuf[++cpos]))                          while (isdigit(cmdp[++cpos]))
                                 ;                                  ;
                         c = cbuf[cpos];                          c = cmdp[cpos];
                         cbuf[cpos] = '\0';                          cmdp[cpos] = '\0';
                         yylval.i = atoi(cp);                          yylval.u.i = atoi(cp);
                         cbuf[cpos] = c;                          cmdp[cpos] = c;
                         state = STR1;                          state = STR1;
                         return (NUMBER);                          return (NUMBER);
                 }                  }
Line 1554  yylex(void)
Line 1619  yylex(void)
                 goto dostr1;                  goto dostr1;
   
         case ARGS:          case ARGS:
                 if (isdigit(cbuf[cpos])) {                  if (isdigit(cmdp[cpos])) {
                         cp = &cbuf[cpos];                          cp = &cmdp[cpos];
                         while (isdigit(cbuf[++cpos]))                          while (isdigit(cmdp[++cpos]))
                                 ;                                  ;
                         c = cbuf[cpos];                          c = cmdp[cpos];
                         cbuf[cpos] = '\0';                          cmdp[cpos] = '\0';
                         yylval.i = atoi(cp);                          yylval.u.i = atoi(cp);
                         cbuf[cpos] = c;                          yylval.u.o = strtoull(cp, (char **)NULL, 10);
                           cmdp[cpos] = c;
                         return (NUMBER);                          return (NUMBER);
                 }                  }
                 if (strncasecmp(&cbuf[cpos], "ALL", 3) == 0                  if (strncasecmp(&cmdp[cpos], "ALL", 3) == 0
                  && !isalnum(cbuf[cpos + 3])) {                   && !isalnum(cmdp[cpos + 3])) {
                         yylval.s = xstrdup("ALL");                          yylval.s = xstrdup("ALL");
                         cpos += 3;                          cpos += 3;
                         return ALL;                          return ALL;
                 }                  }
                 switch (cbuf[cpos++]) {                  switch (cmdp[cpos++]) {
   
                 case '\n':                  case '\n':
                         state = CMD;                          state = EOLN;
                         return (CRLF);                          return (CRLF);
   
                 case ' ':                  case ' ':
Line 1634  yylex(void)
Line 1700  yylex(void)
                 break;                  break;
   
         case NOARGS:          case NOARGS:
                 if (cbuf[cpos] == '\n') {                  if (cmdp[cpos] == '\n') {
                         state = CMD;                          state = EOLN;
                         return (CRLF);                          return (CRLF);
                 }                  }
                 c = cbuf[cpos];                  c = cmdp[cpos];
                 cbuf[cpos] = '\0';                  cmdp[cpos] = '\0';
                 reply(501, "'%s' command does not take any arguments.", cbuf);                  reply(501, "'%s' command does not take any arguments.", cmdp);
                 hasyyerrored = 1;                  hasyyerrored = 1;
                 cbuf[cpos] = c;                  cmdp[cpos] = c;
                 break;                  break;
   
           case EOLN:
                   state = CMD;
                   return (0);
   
         default:          default:
                 fatal("Unknown state in scanner.");                  fatal("Unknown state in scanner.");
         }          }
         yyerror(NULL);          yyerror(NULL);
         state = CMD;          state = CMD;
           is_oob = 0;
         longjmp(errcatch, 0);          longjmp(errcatch, 0);
         /* NOTREACHED */          /* NOTREACHED */
 }  }
Line 1660  yyerror(char *s)
Line 1731  yyerror(char *s)
 {  {
         char *cp;          char *cp;
   
         if (hasyyerrored)          if (hasyyerrored || is_oob)
                 return;                  return;
         if ((cp = strchr(cbuf,'\n')) != NULL)          if ((cp = strchr(cmdp,'\n')) != NULL)
                 *cp = '\0';                  *cp = '\0';
         reply(500, "'%s': command not understood.", cbuf);          reply(500, "'%s': command not understood.", cmdp);
         hasyyerrored = 1;          hasyyerrored = 1;
 }  }
   
Line 1673  help(struct tab *ctab, const char *s)
Line 1744  help(struct tab *ctab, const char *s)
 {  {
         struct tab *c;          struct tab *c;
         int width, NCMDS;          int width, NCMDS;
         char *type;          char *htype;
   
         if (ctab == sitetab)          if (ctab == sitetab)
                 type = "SITE ";                  htype = "SITE ";
         else          else
                 type = "";                  htype = "";
         width = 0, NCMDS = 0;          width = 0, NCMDS = 0;
         for (c = ctab; c->name != NULL; c++) {          for (c = ctab; c->name != NULL; c++) {
                 int len = strlen(c->name);                  int len = strlen(c->name);
Line 1693  help(struct tab *ctab, const char *s)
Line 1764  help(struct tab *ctab, const char *s)
                 int columns, lines;                  int columns, lines;
   
                 reply(-214, "%s", "");                  reply(-214, "%s", "");
                 reply(0, "The following %scommands are recognized.", type);                  reply(0, "The following %scommands are recognized.", htype);
                 reply(0, "(`-' = not implemented, `+' = supports options)");                  reply(0, "(`-' = not implemented, `+' = supports options)");
                 columns = 76 / width;                  columns = 76 / width;
                 if (columns == 0)                  if (columns == 0)
Line 1728  help(struct tab *ctab, const char *s)
Line 1799  help(struct tab *ctab, const char *s)
         }          }
         c = lookup(ctab, s);          c = lookup(ctab, s);
         if (c == (struct tab *)0) {          if (c == (struct tab *)0) {
                 reply(502, "Unknown command %s.", s);                  reply(502, "Unknown command '%s'.", s);
                 return;                  return;
         }          }
         if (CMD_IMPLEMENTED(c))          if (CMD_IMPLEMENTED(c))
                 reply(214, "Syntax: %s%s %s", type, c->name, c->help);                  reply(214, "Syntax: %s%s %s", htype, c->name, c->help);
         else          else
                 reply(214, "%s%-*s\t%s; not implemented.", type, width,                  reply(504, "%s%-*s\t%s; not implemented.", htype, width,
                     c->name, c->help);                      c->name, c->help);
 }  }
   
Line 1746  help(struct tab *ctab, const char *s)
Line 1817  help(struct tab *ctab, const char *s)
 static void  static void
 port_check(const char *cmd, int family)  port_check(const char *cmd, int family)
 {  {
           char h1[NI_MAXHOST], h2[NI_MAXHOST];
           char s1[NI_MAXHOST], s2[NI_MAXHOST];
   #ifdef NI_WITHSCOPEID
           const int niflags = NI_NUMERICHOST | NI_NUMERICSERV | NI_WITHSCOPEID;
   #else
           const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
   #endif
   
         if (epsvall) {          if (epsvall) {
                 reply(501, "%s disallowed after EPSV ALL", cmd);                  reply(501, "%s disallowed after EPSV ALL", cmd);
Line 1763  port_check(const char *cmd, int family)
Line 1841  port_check(const char *cmd, int family)
   
                         /* be paranoid, if told so */                          /* be paranoid, if told so */
         if (CURCLASS_FLAGS_ISSET(checkportcmd)) {          if (CURCLASS_FLAGS_ISSET(checkportcmd)) {
                 if ((ntohs(data_dest.su_port) < IPPORT_RESERVED) ||  
                     (data_dest.su_len != his_addr.su_len))  
                         goto port_check_fail;  
                 switch (data_dest.su_family) {  
                 case AF_INET:  
                         if (memcmp(&data_dest.su_addr, &his_addr.su_addr,  
                             data_dest.su_len) != 0)  
                                 goto port_check_fail;  
                         break;  
 #ifdef INET6  #ifdef INET6
                 case AF_INET6:                  /*
                         if (memcmp(&data_dest.su_6addr, &his_addr.su_6addr,                   * be paranoid, there are getnameinfo implementation that does
                             sizeof(data_dest.su_6addr)) != 0)                   * not present scopeid portion
                                 goto port_check_fail;                   */
                         if (data_dest.su_scope_id != his_addr.su_scope_id)                  if (data_dest.su_family == AF_INET6 &&
                                 goto port_check_fail;                      data_dest.su_scope_id != his_addr.su_scope_id)
                         break;                          goto port_check_fail;
 #endif  #endif
                 default:  
                   if (getnameinfo((struct sockaddr *)&data_dest, data_dest.su_len,
                       h1, sizeof(h1), s1, sizeof(s1), niflags))
                           goto port_check_fail;
                   if (getnameinfo((struct sockaddr *)&his_addr, his_addr.su_len,
                       h2, sizeof(h2), s2, sizeof(s2), niflags))
                           goto port_check_fail;
   
                   if (atoi(s1) < IPPORT_RESERVED || strcmp(h1, h2) != 0)
                         goto port_check_fail;                          goto port_check_fail;
                 }  
         }          }
   
         usedefault = 0;          usedefault = 0;

Legend:
Removed from v.1.48.2.2  
changed lines
  Added in v.1.72

CVSweb <webmaster@jp.NetBSD.org>