📄 ftp.c
字号:
void abort_remote(FILE *din) { char buf[BUFSIZ]; int nfnd; fd_set mask; /* * send IAC in urgent mode instead of DM because 4.3BSD places oob mark * after urgent byte rather than before as is protocol now */ sprintf(buf, "%c%c%c", IAC, IP, IAC); if (send(fileno(cout), buf, 3, MSG_OOB) != 3) perror("abort"); fprintf(cout,"%cABOR\r\n", DM); fflush(cout); FD_ZERO(&mask); FD_SET(fileno(cin), &mask); if (din) { FD_SET(fileno(din), &mask); } if ((nfnd = empty(&mask, 10)) <= 0) { if (nfnd < 0) { perror("abort"); } if (ptabflg) code = -1; lostpeer(); } if (din && FD_ISSET(fileno(din), &mask)) { while (read(fileno(din), buf, BUFSIZ) > 0) /* LOOP */; } if (getreply(0) == ERROR && code == 552) { /* 552 needed for nic style abort */ getreply(0); } getreply(0);}void proxtrans(char *cmd, char *local, char *remote) { Sig_t oldintr; int secndflag = 0, prox_type, nfnd; extern jmp_buf ptabort; char *cmd2; fd_set mask; void abortpt(); if (strcmp(cmd, "RETR")) cmd2 = "RETR"; else cmd2 = runique ? "STOU" : "STOR"; if ((prox_type = type) == 0) { if (unix_server && unix_proxy) prox_type = TYPE_I; else prox_type = TYPE_A; } if (curtype != prox_type) changetype(prox_type, 1); if (command("PASV\r\n") != COMPLETE) { printf("proxy server does not support third party transfers.\n"); return; } pswitch(0); if (!connected) { printf("No primary connection\n"); pswitch(1); code = -1; return; } if (curtype != prox_type) changetype(prox_type, 1); if (command("PORT %s\r\n", pasv) != COMPLETE) { pswitch(1); return; } if (setjmp(ptabort)) goto abort; oldintr = Signal(SIGINT, abortpt); if (command("%s %s\r\n", cmd, remote) != PRELIM) { Signal(SIGINT, oldintr); pswitch(1); return; } sleep(2); pswitch(1); secndflag++; if (command("%s %s\r\n", cmd2, local) != PRELIM) goto abort; ptflag++; getreply(0); pswitch(0); getreply(0); Signal(SIGINT, oldintr); pswitch(1); ptflag = 0; printf("local: %s remote: %s\n", local, remote); return;abort: Signal(SIGINT, SIG_IGN); ptflag = 0; if (strcmp(cmd, "RETR") && !proxy) pswitch(1); else if (!strcmp(cmd, "RETR") && proxy) pswitch(0); if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */ if (command("%s %s\r\n", cmd2, local) != PRELIM) { pswitch(0); if (cpend) abort_remote((FILE *) NULL); } pswitch(1); if (ptabflg) code = -1; Signal(SIGINT, oldintr); return; } if (cpend) abort_remote((FILE *) NULL); pswitch(!proxy); if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */ if (command("%s %s\r\n", cmd2, local) != PRELIM) { pswitch(0); if (cpend) abort_remote((FILE *) NULL); pswitch(1); if (ptabflg) code = -1; Signal(SIGINT, oldintr); return; } } if (cpend) abort_remote((FILE *) NULL); pswitch(!proxy); if (cpend) { FD_ZERO(&mask); FD_SET(fileno(cin), &mask); if ((nfnd = empty(&mask, 10)) <= 0) { if (nfnd < 0) perror("abort"); if (ptabflg) code = -1; lostpeer(); } getreply(0); getreply(0); } if (proxy) pswitch(0); pswitch(1); if (ptabflg) code = -1; Signal(SIGINT, oldintr);}/* * Need to start a listen on the data channel before we send the command, * otherwise the server's connect may fail. */int initconn() { register char *p, *a; int result, len, tmpno = 0; int on = 1;noport: data_addr = myctladdr; if (sendport) data_addr.sin_port = 0; /* let system pick one */ if (data != -1) close(data); data = socket(AF_INET, SOCK_STREAM, 0); if (data < 0) { perror("ftp: socket"); if (tmpno) sendport = 1; return (1); } if (!sendport) if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) { perror("ftp: setsockopt (reuse address)"); goto bad; } if (bind(data, (struct sockaddr *)&data_addr, sizeof(data_addr)) < 0) { perror("ftp: bind"); goto bad; } if (options & SO_DEBUG && setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0) perror("ftp: setsockopt (ignored)"); len = sizeof (data_addr); if (getsockname(data, (struct sockaddr *)&data_addr, &len) < 0) { perror("ftp: getsockname"); goto bad; } if (listen(data, 1) < 0) perror("ftp: listen"); if (sendport) { a = (char *)&data_addr.sin_addr; p = (char *)&data_addr.sin_port;#define UC(b) (((int)b)&0xff) result = command("PORT %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])); if (result == ERROR && sendport == -1) { sendport = 0; tmpno = 1; goto noport; } return (result != COMPLETE); } if (tmpno) sendport = 1;#if defined(IP_TOS) && defined(IPTOS_THROUGHPUT) on = IPTOS_THROUGHPUT; if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0) perror("ftp: setsockopt TOS (ignored)");#endif return (0);bad: close(data), data = -1; if (tmpno) sendport = 1; return (1);}void sendrequest(char *cmd, char *local, char *remote, int printnames) { struct stat st; struct timeval start, stop; register int c, d; FILE *fin, *dout = 0, *popen(); int (*closefunc)(), pclose(), fclose(); Sig_t oldintr, oldintp; long bytes = 0, hashbytes = HASHBYTES; char *lmode, buf[BUFSIZ], *bufp; void abortsend(); if (verbose && printnames) { if (local && *local != '-') printf("local: %s ", local); if (remote) printf("remote: %s\n", remote); } if (proxy) { proxtrans(cmd, local, remote); return; } if (curtype != type) changetype(type, 0); closefunc = NULL; oldintr = NULL; oldintp = NULL; lmode = "w"; if (setjmp(sendabort)) { while (cpend) { getreply(0); } if (data >= 0) { close(data); data = -1; } if (oldintr) Signal(SIGINT,oldintr); if (oldintp) Signal(SIGPIPE,oldintp); code = -1; return; } oldintr = Signal(SIGINT, abortsend); if (strcmp(local, "-") == 0) fin = stdin; else if (*local == '|') { oldintp = Signal(SIGPIPE,SIG_IGN); fin = popen(local + 1, "r"); if (fin == NULL) { perror(local + 1); Signal(SIGINT, oldintr); Signal(SIGPIPE, oldintp); code = -1; return; } closefunc = pclose; } else { fin = fopen(local, "r"); if (fin == NULL) { fprintf(stderr, "local: %s: %s\n", local, strerror(errno)); Signal(SIGINT, oldintr); code = -1; return; } closefunc = fclose; if (fstat(fileno(fin), &st) < 0 || (st.st_mode&S_IFMT) != S_IFREG) { fprintf(stdout, "%s: not a plain file.\n", local); Signal(SIGINT, oldintr); fclose(fin); code = -1; return; } } if (initconn()) { Signal(SIGINT, oldintr); if (oldintp) Signal(SIGPIPE, oldintp); code = -1; if (closefunc != NULL) (*closefunc)(fin); return; } if (setjmp(sendabort)) { goto abort; } if (restart_point && (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) { if (fseek(fin, (long) restart_point, 0) < 0) { fprintf(stderr, "local: %s: %s\n", local, strerror(errno)); restart_point = 0; if (closefunc != NULL) (*closefunc)(fin); return; } if (command("REST %ld\r\n", (long) restart_point) != CONTINUE) { restart_point = 0; if (closefunc != NULL) (*closefunc)(fin); return; } restart_point = 0; lmode = "r+w"; } if (remote) { if (command("%s %s\r\n", cmd, remote) != PRELIM) { Signal(SIGINT, oldintr); if (oldintp) Signal(SIGPIPE, oldintp); if (closefunc != NULL) (*closefunc)(fin); return; } } else if (command("%s\r\n", cmd) != PRELIM) { Signal(SIGINT, oldintr); if (oldintp) Signal(SIGPIPE, oldintp); if (closefunc != NULL) (*closefunc)(fin); return; } dout = dataconn(lmode); if (dout == NULL) goto abort; gettimeofday(&start, (struct timezone *)0); oldintp = Signal(SIGPIPE, SIG_IGN); switch (curtype) { case TYPE_I: case TYPE_L: errno = d = 0; while ((c = read(fileno(fin), buf, sizeof (buf))) > 0) { bytes += c; for (bufp = buf; c > 0; c -= d, bufp += d) if ((d = write(fileno(dout), bufp, c)) <= 0) break; if (hash) { while (bytes >= hashbytes) { putchar('#'); hashbytes += HASHBYTES; } fflush(stdout); } } if (hash && bytes > 0) { if (bytes < HASHBYTES) putchar('#'); putchar('\n'); fflush(stdout); } if (c < 0) fprintf(stderr, "local: %s: %s\n", local, strerror(errno)); if (d < 0) { if (errno != EPIPE) perror("netout"); bytes = -1; } break; case TYPE_A: while ((c = getc(fin)) != EOF) { if (c == '\n') { while (hash && (bytes >= hashbytes)) { putchar('#'); fflush(stdout); hashbytes += HASHBYTES; } if (ferror(dout)) break; putc('\r', dout); bytes++; } putc(c, dout); bytes++; } if (hash) { if (bytes < hashbytes) putchar('#'); putchar('\n'); fflush(stdout); } if (ferror(fin)) fprintf(stderr, "local: %s: %s\n", local, strerror(errno)); if (ferror(dout)) { if (errno != EPIPE) perror("netout"); bytes = -1; } break; } gettimeofday(&stop, (struct timezone *)0); if (closefunc != NULL) (*closefunc)(fin); fclose(dout); if(data >= 0) { close(data); data = -1; } getreply(0); Signal(SIGINT, oldintr); if (oldintp) Signal(SIGPIPE, oldintp); if (bytes > 0) {#ifdef FASCIST syslog(LOG_NOTICE, "Sent local file %s as %s -- %d bytes", local, remote, bytes);#endif ptransfer("sent", bytes, &start, &stop); } return;abort: gettimeofday(&stop, (struct timezone *)0); Signal(SIGINT, oldintr); if (oldintp) Signal(SIGPIPE, oldintp); if (!cpend) { code = -1; return; } if (data >= 0) { close(data); data = -1; } if (dout) fclose(dout); getreply(0); code = -1; if (closefunc != NULL && fin != NULL) (*closefunc)(fin); if (bytes > 0) {#ifdef FASCIST syslog(LOG_NOTICE, "Sent local file %s as %s -- %d bytes", local, remote, bytes);#endif ptransfer("sent", bytes, &start, &stop); }}jmp_buf recvabort;voidabortrecv(){ mflag = 0; abrtflag = 0; printf("\nreceive aborted\nwaiting for remote to finish abort\n"); fflush(stdout); longjmp(recvabort, 1);}void recvrequest(char *cmd, char *local, char *remote, char *lmode, int printnames) { FILE *fout, *din = 0, *popen(); int (*closefunc)(), pclose(), fclose(); Sig_t oldintr, oldintp; int is_retr, tcrflag, bare_lfs = 0; char *gunique(); static int bufsize; static char *buf; long bytes = 0, hashbytes = HASHBYTES; register int c, d; struct timeval start, stop; struct stat st; off_t lseek(); void abortrecv(); is_retr = strcmp(cmd, "RETR") == 0; if (is_retr && verbose && printnames) { if (local && *local != '-') printf("local: %s ", local); if (remote) printf("remote: %s\n", remote); } if (proxy && is_retr) { proxtrans(cmd, local, remote); return; } closefunc = NULL; oldintr = NULL; oldintp = NULL; tcrflag = !crflag && is_retr; if (setjmp(recvabort)) { while (cpend) { getreply(0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -