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

📄 ftpd.c

📁 linux下ftpd服务器端的源码实现
💻 C
📖 第 1 页 / 共 4 页
字号:
#else  va_start (ap);#endif  printf ("%d ", n);  vprintf (fmt, ap);  printf ("\r\n");  fflush (stdout);  if (debug)    {      syslog (LOG_DEBUG, "<--- %d ", n);      vsyslog (LOG_DEBUG, fmt, ap);    }}voidlreply (int n, const char *fmt, ...){  va_list ap;#if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__  va_start (ap, fmt);#else  va_start (ap);#endif  printf ("%d- ", n);  vprintf (fmt, ap);  printf ("\r\n");  fflush (stdout);  if (debug)    {      syslog (LOG_DEBUG, "<--- %d- ", n);      vsyslog (LOG_DEBUG, fmt, ap);    }}static voidack (const char *s){  reply (250, "%s command successful.", s);}voidnack (const char *s){  reply (502, "%s command not implemented.", s);}voiddelete (const char *name){  struct stat st;  LOGCMD ("delete", name);  if (stat (name, &st) < 0)    {      perror_reply (550, name);      return;    }  if (S_ISDIR (st.st_mode))    {      if (rmdir (name) < 0)	{	  perror_reply (550, name);	  return;	}      goto done;    }  if (unlink (name) < 0)    {      perror_reply (550, name);      return;    } done:  ack ("DELE");}voidcwd (const char *path){  if (chdir (path) < 0)    perror_reply (550, path);  else    ack ("CWD");}voidmakedir (const char *name){  extern char *xgetcwd (void);  LOGCMD ("mkdir", name);  if (mkdir (name, 0777) < 0)    perror_reply (550, name);  else if (name[0] == '/')    reply (257, "\"%s\" new directory created.");  else    {      /* We have to figure out what our current directory is so that we can	 give an absolute name in the reply.  */      char *current = xgetcwd ();      if (current)	{	  if (current[1] == '\0')	    current[0] = '\0';	  reply (257, "\"%s/%s\" new directory created.", current, name);	  free (current);	}      else	reply (257, "(unknown absolute name) new directory created.");    }}voidremovedir (const char *name){  LOGCMD ("rmdir", name);  if (rmdir (name) < 0)    perror_reply (550, name);  else    ack("RMD");}voidpwd (void){  extern char *xgetcwd (void);  char *path = xgetcwd ();  if (path)    {      reply (257, "\"%s\" is current directory.", path);      free (path);    }  else    reply (550, "%s.", strerror (errno));}char *renamefrom (const char *name){  struct stat st;  if (stat (name, &st) < 0)    {      perror_reply (550, name);      return ((char *)0);    }  reply (350, "File exists, ready for destination name");  return (char *)(name);}voidrenamecmd (const char *from, const char *to){  LOGCMD2 ("rename", from, to);  if (rename (from, to) < 0)    perror_reply (550, "rename");  else    ack ("RNTO");}static voiddolog (struct sockaddr_in *sin, struct credentials *pcred){  const char *name;  struct hostent *hp = gethostbyaddr ((char *)&sin->sin_addr,				      sizeof (struct in_addr), AF_INET);  if (hp)    name = hp->h_name;  else    name = inet_ntoa (sin->sin_addr);  if (pcred->remotehost)    free (pcred->remotehost);  pcred->remotehost = sgetsave (name);#ifdef HAVE_SETPROCTITLE  snprintf (proctitle, sizeof (proctitle), "%s: connected", pcred->remotehost);  setproctitle ("%s",proctitle);#endif /* HAVE_SETPROCTITLE */  if (logging)    syslog (LOG_INFO, "connection from %s", pcred->remotehost);}/*  Record logout in wtmp file    and exit with supplied status.  */voiddologout (int status){  /* Racing condition with SIGURG: If SIGURG is receive     here, it will jump back has root in the main loop     David Greenman:dg@root.com.  */  transflag = 0;  if (cred.logged_in)    {      seteuid ((uid_t)0);      logwtmp_keep_open (ttyline, "", "");    }  /* beware of flushing buffers after a SIGPIPE */  _exit (status);}static RETSIGTYPEmyoob (int signo ARG_UNUSED){  char *cp;  /* only process if transfer occurring */  if (!transflag)    return;  cp = tmpline;  if (telnet_fgets (cp, 7, stdin) == NULL)    {      reply (221, "You could at least say goodbye.");      dologout (0);    }  upper (cp);  if (strcmp (cp, "ABOR\r\n") == 0)    {      tmpline[0] = '\0';      reply (426, "Transfer aborted. Data connection closed.");      reply (226, "Abort successful");      longjmp (urgcatch, 1);    }  if (strcmp (cp, "STAT\r\n") == 0)    {      if (file_size != (off_t) -1)	reply (213, "Status: %s of %s bytes transferred",	       off_to_str (byte_count), off_to_str (file_size));      else	reply (213, "Status: %s bytes transferred",	       off_to_str (byte_count));    }}/* Note: a response of 425 is not mentioned as a possible response to   the PASV command in RFC959. However, it has been blessed as   a legitimate response by Jon Postel in a telephone conversation   with Rick Adams on 25 Jan 89.  */voidpassive (void){  int len;  char *p, *a;  pdata = socket (AF_INET, SOCK_STREAM, 0);  if (pdata < 0)    {      perror_reply (425, "Can't open passive connection");      return;    }  pasv_addr = ctrl_addr;  pasv_addr.sin_port = 0;  seteuid ((uid_t)0);  if (bind (pdata, (struct sockaddr *)&pasv_addr, sizeof (pasv_addr)) < 0)    {      seteuid ((uid_t)cred.uid);      goto pasv_error;    }  seteuid ((uid_t)cred.uid);  len = sizeof(pasv_addr);  if (getsockname (pdata, (struct sockaddr *) &pasv_addr, &len) < 0)    goto pasv_error;  if (listen (pdata, 1) < 0)    goto pasv_error;  a = (char *) &pasv_addr.sin_addr;  p = (char *) &pasv_addr.sin_port;#define UC(b) (((int) b) & 0xff)  reply (227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d)", UC(a[0]),	 UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));  return; pasv_error:  close (pdata);  pdata = -1;  perror_reply (425, "Can't open passive connection");  return;}/* Generate unique name for file with basename "local".   The file named "local" is already known to exist.   Generates failure reply on error.  */static char *gunique (const char *local){  static char *string = 0;  struct stat st;  int count;  char *cp;  cp = strrchr (local, '/');  if (cp)    *cp = '\0';  if (stat(cp ? local : ".", &st) < 0)    {      perror_reply (553, cp ? local : ".");      return ((char *) 0);    }  if (cp)    *cp = '/';  if (string)    free (string);  string = malloc (strlen (local) + 5); /* '.' + DIG + DIG + '\0' */  if (string)    {      strcpy (string, local);      cp = string + strlen (string);      *cp++ = '.';      for (count = 1; count < 100; count++)	{	  sprintf (cp, "%d", count);	  if (stat (string, &st) < 0)	    return string;	}    }  reply (452, "Unique file name cannot be created.");  return NULL;}/* * Format and send reply containing system error number. */voidperror_reply (int code, const char *string){  reply (code, "%s: %s.", string, strerror (errno));}static char *onefile[] = {	"",	0};voidsend_file_list (const char *whichf){  struct stat st;  DIR *dirp = NULL;  struct dirent *dir;  FILE *dout = NULL;  char **dirlist, *dirname;  int simple = 0;  int freeglob = 0;  glob_t gl;  char *p = NULL;  if (strpbrk(whichf, "~{[*?") != NULL)    {      int flags = GLOB_NOCHECK;#ifdef GLOB_BRACE      flags |= GLOB_BRACE;#endif#ifdef GLOB_QUOTE      flags |= GLOB_QUOTE;#endif#ifdef GLOB_TILDE      flags |= GLOB_TILDE;#endif      memset (&gl, 0, sizeof (gl));      freeglob = 1;      if (glob (whichf, flags, 0, &gl))	{	  reply (550, "not found");	  goto out;	}      else if (gl.gl_pathc == 0)	{	  errno = ENOENT;	  perror_reply (550, whichf);	  goto out;	}      dirlist = gl.gl_pathv;    }  else    {      p = strdup (whichf);      onefile[0] = p;      dirlist = onefile;      simple = 1;    }  if (setjmp (urgcatch))    {      transflag = 0;      goto out;    }  while ((dirname = *dirlist++))    {      if (stat (dirname, &st) < 0)	{	  /* If user typed "ls -l", etc, and the client	     used NLST, do what the user meant.  */	  if (dirname[0] == '-' && *dirlist == NULL	      && transflag == 0)	    {	      retrieve ("/bin/ls %s", dirname);	      goto out;	    }	  perror_reply (550, whichf);	  if (dout != NULL)	    {	      fclose (dout);	      transflag = 0;	      data = -1;	      pdata = -1;	    }	  goto out;	}      if (S_ISREG(st.st_mode))	{	  if (dout == NULL)	    {	      dout = dataconn ("file list", (off_t)-1, "w");	      if (dout == NULL)		goto out;	      transflag++;	    }	  fprintf (dout, "%s%s\n", dirname,		   type == TYPE_A ? "\r" : "");	  byte_count += strlen (dirname) + 1;	  continue;	}      else if (!S_ISDIR (st.st_mode))	continue;      dirp = opendir (dirname);      if (dirp == NULL)	continue;      while ((dir = readdir (dirp)) != NULL)	{	  char *nbuf;	  if (dir->d_name[0] == '.' && dir->d_name[1] == '\0')	    continue;	  if (dir->d_name[0] == '.' && dir->d_name[1] == '.' &&	      dir->d_name[2] == '\0')	    continue;	  nbuf = (char *) alloca (strlen (dirname) + 1 +				  strlen (dir->d_name) + 1);	  sprintf (nbuf, "%s/%s", dirname, dir->d_name);	  /* We have to do a stat to insure it's	     not a directory or special file.  */	  if (simple || (stat (nbuf, &st) == 0			 && S_ISREG(st.st_mode)))	    {	      if (dout == NULL)		{		  dout = dataconn ("file list", (off_t)-1, "w");		  if (dout == NULL)		    goto out;		  transflag++;		}	      if (nbuf[0] == '.' && nbuf[1] == '/')		fprintf (dout, "%s%s\n", &nbuf[2], type == TYPE_A ? "\r" : "");	      else		fprintf (dout, "%s%s\n", nbuf, type == TYPE_A ? "\r" : "");	      byte_count += strlen (nbuf) + 1;	    }	}      closedir (dirp);    }  if (dout == NULL)    reply (550, "No files found.");  else if (ferror (dout) != 0)    perror_reply (550, "Data connection");  else    reply (226, "Transfer complete.");  transflag = 0;  if (dout != NULL)    fclose (dout);  data = -1;  pdata = -1; out:  if (p)    free (p);  if (freeglob)    {      freeglob = 0;      globfree (&gl);    }}

⌨️ 快捷键说明

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