⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ftpd.c

📁 linux下ftpd服务器端的源码实现
💻 C
📖 第 1 页 / 共 4 页
字号:
      if (unique)	reply (226, "Transfer complete (unique file name:%s).", name);      else	reply (226, "Transfer complete.");    }  fclose (din);  data = -1;  pdata = -1; done:  LOGBYTES (*mode == 'w' ? "put" : "append", name, byte_count);  (*closefunc) (fout);}static FILE *getdatasock (const char *mode){  int s, t, tries;  if (data >= 0)    return fdopen (data, mode);  seteuid ((uid_t)0);  s = socket (AF_INET, SOCK_STREAM, 0);  if (s < 0)    goto bad;  /* Enables local reuse address.  */  {    int on = 1;    if (setsockopt (s, SOL_SOCKET, SO_REUSEADDR,		    (char *) &on, sizeof(on)) < 0)      goto bad;  }  /* anchor socket to avoid multi-homing problems */  data_source.sin_family = AF_INET;  data_source.sin_addr = ctrl_addr.sin_addr;  for (tries = 1; ; tries++)    {      if (bind (s, (struct sockaddr *)&data_source,		sizeof(data_source)) >= 0)	break;      if (errno != EADDRINUSE || tries > 10)	goto bad;      sleep (tries);    }  seteuid ((uid_t)cred.uid);#if defined (IP_TOS) && defined (IPTOS_THROUGHPUT) && defined (IPPROTO_IP)  {    int on = IPTOS_THROUGHPUT;    if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0)      syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");  }#endif  return (fdopen(s, mode)); bad:  /* Return the real value of errno (close may change it) */  t = errno;  seteuid ((uid_t)cred.uid);  close(s);  errno = t;  return NULL;}static FILE *dataconn (const char *name, off_t size, const char *mode){  char sizebuf[32];  FILE *file;  int retry = 0;  file_size = size;  byte_count = 0;  if (size != (off_t) -1)    snprintf(sizebuf, sizeof(sizebuf), " (%s bytes)",		    off_to_str (size));  else    *sizebuf = '\0';  if (pdata >= 0)    {      struct sockaddr_in from;      int s, fromlen = sizeof (from);      signal (SIGALRM, toolong);      alarm ((unsigned) timeout);      s = accept (pdata, (struct sockaddr *)&from, &fromlen);      alarm (0);      if (s < 0)	{	  reply(425, "Can't open data connection.");	  close (pdata);	  pdata = -1;	  return NULL;	}      close (pdata);      pdata = s;#if defined (IP_TOS) && defined (IPTOS_THROUGHPUT) && defined (IPPROTO_IP)      /* Optimize throughput.  */      {	int tos = IPTOS_THROUGHPUT;	setsockopt (s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof (int));      }#endif#ifdef SO_KEEPALIVE      /* Set keepalives on the socket to detect dropped conns.  */      {	int keepalive = 1;	setsockopt (s, SOL_SOCKET, SO_KEEPALIVE,			   (char *)&keepalive, sizeof (int));      }#endif      reply (150, "Opening %s mode data connection for '%s'%s.",	     type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);      return fdopen (pdata, mode);    }  if (data >= 0)    {      reply (125, "Using existing data connection for '%s'%s.",	     name, sizebuf);      usedefault = 1;      return fdopen (data, mode);    }  if (usedefault)    data_dest = his_addr;  usedefault = 1;  file = getdatasock (mode);  if (file == NULL)    {      reply (425, "Can't create data socket (%s,%d): %s.",	     inet_ntoa (data_source.sin_addr),	     ntohs (data_source.sin_port), strerror(errno));      return NULL;    }  data = fileno (file);  while (connect (data, (struct sockaddr *)&data_dest,		  sizeof (data_dest)) < 0)    {      if (errno == EADDRINUSE && retry < swaitmax)	{	  sleep ((unsigned) swaitint);	  retry += swaitint;	  continue;	}      perror_reply (425, "Can't build data connection");      fclose (file);      data = -1;      return NULL;    }  reply (150, "Opening %s mode data connection for '%s'%s.",	 type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);  return file;}/* Tranfer the contents of "instr" to "outstr" peer using the appropriate   encapsulation of the data subject * to Mode, Structure, and Type.   NB: Form isn't handled.  */static voidsend_data (FILE *instr, FILE *outstr, off_t blksize){  int c, cnt, filefd, netfd;  char *buf, *bp;  off_t curpos;  size_t len, filesize;  transflag++;  if (setjmp (urgcatch))    {      transflag = 0;      return;    }  netfd = fileno (outstr);  filefd = fileno (instr);#ifdef HAVE_MMAP  if (file_size > 0)    {      curpos = lseek (filefd, 0, SEEK_CUR);      if (curpos >= 0)	{	  filesize = file_size - curpos;	  buf = mmap (0, filesize, PROT_READ, MAP_SHARED, filefd, curpos);	}    }#endif  switch (type)    {    case TYPE_A:#ifdef HAVE_MMAP      if (file_size > 0 && curpos >= 0 && buf != MAP_FAILED)	{	  len = 0;	  while (len < filesize)	    {	      byte_count++;	      if (buf[len] == '\n')		{		  if (ferror (outstr))		    break;		  putc ('\r', outstr);		}	      putc (buf[len], outstr);	      len++;	    }	  fflush (outstr);	  transflag = 0;	  munmap (buf, filesize);	  if (ferror (outstr))	    goto data_err;	  reply (226, "Transfer complete.");	  return;	}#endif      while ((c = getc (instr)) != EOF)	{	  byte_count++;	  if (c == '\n')	    {	      if (ferror (outstr))		goto data_err;	      putc ('\r', outstr);	    }	  putc (c, outstr);	}      fflush (outstr);      transflag = 0;      if (ferror (instr))	goto file_err;      if (ferror (outstr))	goto data_err;      reply (226, "Transfer complete.");      return;    case TYPE_I:    case TYPE_L:#ifdef HAVE_MMAP      if (file_size > 0 && curpos >= 0 && buf != MAP_FAILED)	{	  bp = buf;	  len = filesize;	  do	    {	      cnt = write (netfd, bp, len);	      len -= cnt;	      bp += cnt;	      if (cnt > 0) byte_count += cnt;	    } while (cnt > 0 && len > 0);	  transflag = 0;	  munmap (buf, (size_t)filesize);	  if (cnt < 0)	    goto data_err;	  reply (226, "Transfer complete.");	  return;	}#endif      buf = malloc ((u_int)blksize);      if (buf == NULL)	{	  transflag = 0;	  perror_reply (451, "Local resource failure: malloc");	  return;	}      while ((cnt = read (filefd, buf, (u_int)blksize)) > 0 &&	     write(netfd, buf, cnt) == cnt)	byte_count += cnt;      transflag = 0;      free (buf);      if (cnt != 0)	{	  if (cnt < 0)	    goto file_err;	  goto data_err;	}      reply (226, "Transfer complete.");      return;    default:      transflag = 0;      reply (550, "Unimplemented TYPE %d in send_data", type);      return;    } data_err:  transflag = 0;  perror_reply (426, "Data connection");  return; file_err:  transflag = 0;  perror_reply (551, "Error on input file");}/* Transfer data from peer to "outstr" using the appropriate encapulation of   the data subject to Mode, Structure, and Type.   N.B.: Form isn't handled.  */static intreceive_data (FILE *instr, FILE *outstr){  int c;  int cnt, bare_lfs = 0;  char buf[BUFSIZ];  transflag++;  if (setjmp (urgcatch))    {      transflag = 0;      return -1;    }  switch (type)    {    case TYPE_I:    case TYPE_L:      while ((cnt = read (fileno(instr), buf, sizeof(buf))) > 0)	{	  if (write (fileno (outstr), buf, cnt) != cnt)	    goto file_err;	  byte_count += cnt;	}      if (cnt < 0)	goto data_err;      transflag = 0;      return 0;    case TYPE_E:      reply (553, "TYPE E not implemented.");      transflag = 0;      return -1;    case TYPE_A:      while ((c = getc (instr)) != EOF)	{	  byte_count++;	  if (c == '\n')	    bare_lfs++;	  while (c == '\r')	    {	      if (ferror (outstr))		goto data_err;	      c = getc (instr);	      if (c != '\n')		{		  putc ('\r', outstr);		  if (c == '\0' || c == EOF)		    goto contin2;		}	    }	  putc (c, outstr);	contin2:	;	}      fflush(outstr);      if (ferror (instr))	goto data_err;      if (ferror (outstr))	goto file_err;      transflag = 0;      if (bare_lfs)	{	  lreply (226, "WARNING! %d bare linefeeds received in ASCII mode",		  bare_lfs);	  printf ("   File may not have transferred correctly.\r\n");	}      return (0);    default:      reply (550, "Unimplemented TYPE %d in receive_data", type);      transflag = 0;      return -1;    } data_err:  transflag = 0;  perror_reply (426, "Data Connection");  return -1; file_err:  transflag = 0;  perror_reply (452, "Error writing file");  return -1;}voidstatfilecmd (const char *filename){  FILE *fin;  int c;  char line[LINE_MAX];  snprintf (line, sizeof(line), "/bin/ls -lgA %s", filename);  fin = ftpd_popen (line, "r");  lreply (211, "status of %s:", filename);  while ((c = getc (fin)) != EOF)    {      if (c == '\n')	{	  if (ferror (stdout))	    {	      perror_reply (421, "control connection");	      ftpd_pclose (fin);	      dologout (1);				/* NOTREACHED */	    }	  if (ferror (fin))	    {	      perror_reply (551, filename);	      ftpd_pclose (fin);	      return;	    }	  putc ('\r', stdout);	}      putc (c, stdout);    }  ftpd_pclose (fin);  reply (211, "End of Status");}voidstatcmd (void){  struct sockaddr_in *sin;  u_char *a, *p;  lreply (211, "%s FTP server status:", hostname);  if (!no_version)    printf ("     ftpd (%s) %s\r\n",	    PACKAGE_NAME, PACKAGE_VERSION);  printf ("     Connected to %s", cred.remotehost);  if (!isdigit (cred.remotehost[0]))    printf (" (%s)", inet_ntoa (his_addr.sin_addr));  printf ("\r\n");  if (cred.logged_in)    {      if (cred.guest)	printf ("     Logged in anonymously\r\n");      else	printf ("     Logged in as %s\r\n", cred.name);    }  else if (askpasswd)    printf ("     Waiting for password\r\n");  else    printf ("     Waiting for user name\r\n");  printf ("     TYPE: %s", typenames[type]);  if (type == TYPE_A || type == TYPE_E)    printf (", FORM: %s", formnames[form]);  if (type == TYPE_L)#ifdef CHAR_BIT    printf (" %d", CHAR_BIT);#else#if NBBY == 8  printf (" %d", NBBY);#else  printf (" %d", bytesize);	/* need definition! */#endif#endif  printf ("; STRUcture: %s; transfer MODE: %s\r\n",	  strunames[stru], modenames[stru_mode]);  if (data != -1)    printf ("     Data connection open\r\n");  else if (pdata != -1)    {      printf ("     in Passive mode");      sin = &pasv_addr;      goto printaddr;    }  else if (usedefault == 0)    {      printf ("     PORT");      sin = &data_dest;    printaddr:      a = (u_char *) &sin->sin_addr;      p = (u_char *) &sin->sin_port;#define UC(b) (((int) b) & 0xff)      printf (" (%d,%d,%d,%d,%d,%d)\r\n", UC(a[0]),	      UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));#undef UC    }  else    printf ("     No data connection\r\n");  reply (211, "End of status");}voidfatal (const char *s){  reply (451, "Error in server: %s\n", s);  reply (221, "Closing connection due to server error.");  dologout (0);  /* NOTREACHED */}voidreply (int n, const char *fmt, ...){  va_list ap;#if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__  va_start (ap, fmt);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -