📄 ftpd.c
字号:
#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 + -