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