diff options
| author | Yaroslav Tykhiy <ytykhiy@gmail.com> | 2002-02-15 18:02:43 +0000 |
|---|---|---|
| committer | Yaroslav Tykhiy <ytykhiy@gmail.com> | 2002-02-15 18:02:43 +0000 |
| commit | cafc694e09ebcb19f2db65abe1452bd439f3c7f1 (patch) | |
| tree | 108eb2de44f1299ae05a6f503da01477fae198f2 /libexec | |
| parent | e90f396fcb541ef8f42eef744b91ce30ad71211e (diff) | |
Notes
Diffstat (limited to 'libexec')
| -rw-r--r-- | libexec/ftpd/ftpd.c | 117 |
1 files changed, 85 insertions, 32 deletions
diff --git a/libexec/ftpd/ftpd.c b/libexec/ftpd/ftpd.c index 004c27ecd00f..80f19e039cc0 100644 --- a/libexec/ftpd/ftpd.c +++ b/libexec/ftpd/ftpd.c @@ -78,7 +78,6 @@ static const char rcsid[] = #include <netdb.h> #include <pwd.h> #include <grp.h> -#include <setjmp.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> @@ -128,7 +127,6 @@ union sockunion pasv_addr; int daemon_mode; int data; -jmp_buf errcatch, urgcatch; int logged_in; struct passwd *pw; int debug; @@ -153,6 +151,7 @@ int noepsv=0; /* EPSV command is disabled. */ int noretr=0; /* RETR command is disabled. */ int noguestretr=0; /* RETR command is disabled for anon users. */ +static volatile sig_atomic_t recvurg; sig_atomic_t transflag; off_t file_size; off_t byte_count; @@ -245,7 +244,8 @@ static void inithosts __P((void)); static void selecthost __P((union sockunion *)); #endif static void ack __P((char *)); -static void myoob __P((int)); +static void sigurg __P((int)); +static void myoob __P((void)); static int checkuser __P((char *, char *, int)); static FILE *dataconn __P((char *, off_t, char *)); static void dolog __P((struct sockaddr *)); @@ -254,8 +254,9 @@ static void end_login __P((void)); static FILE *getdatasock __P((char *)); static char *gunique __P((char *)); static void lostconn __P((int)); +static void sigquit __P((int)); static int receive_data __P((FILE *, FILE *)); -static void send_data __P((FILE *, FILE *, off_t, off_t, int)); +static int send_data __P((FILE *, FILE *, off_t, off_t, int)); static struct passwd * sgetpwnam __P((char *)); static char *sgetsave __P((char *)); @@ -288,8 +289,11 @@ main(argc, argv, envp) char *bindname = NULL; int family = AF_UNSPEC; int enable_v4 = 0; + struct sigaction sa; tzset(); /* in case no timezone database in ~ftp */ + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESTART; #ifdef OLD_SETPROCTITLE /* @@ -421,7 +425,8 @@ main(argc, argv, envp) syslog(LOG_ERR, "failed to become a daemon"); exit(1); } - (void) signal(SIGCHLD, reapchild); + sa.sa_handler = reapchild; + (void)sigaction(SIGCHLD, &sa, NULL); /* init bind_sa */ memset(&hints, 0, sizeof(hints)); @@ -524,10 +529,23 @@ main(argc, argv, envp) } } - (void) signal(SIGCHLD, SIG_IGN); - (void) signal(SIGPIPE, lostconn); - if (signal(SIGURG, myoob) == SIG_ERR) - syslog(LOG_ERR, "signal: %m"); + sa.sa_handler = SIG_DFL; + (void)sigaction(SIGCHLD, &sa, NULL); + + sa.sa_handler = sigurg; + sa.sa_flags = 0; /* don't restart syscalls for SIGURG */ + (void)sigaction(SIGURG, &sa, NULL); + + sigfillset(&sa.sa_mask); /* block all signals in handler */ + sa.sa_flags = SA_RESTART; + sa.sa_handler = sigquit; + (void)sigaction(SIGHUP, &sa, NULL); + (void)sigaction(SIGINT, &sa, NULL); + (void)sigaction(SIGQUIT, &sa, NULL); + (void)sigaction(SIGTERM, &sa, NULL); + + sa.sa_handler = lostconn; + (void)sigaction(SIGPIPE, &sa, NULL); addrlen = sizeof(ctrl_addr); if (getsockname(0, (struct sockaddr *)&ctrl_addr, &addrlen) < 0) { @@ -612,7 +630,6 @@ main(argc, argv, envp) hostname[MAXHOSTNAMELEN - 1] = '\0'; #endif reply(220, "%s FTP server (%s) ready.", hostname, version); - (void) setjmp(errcatch); for (;;) (void) yyparse(); /* NOTREACHED */ @@ -628,6 +645,15 @@ lostconn(signo) dologout(1); } +static void +sigquit(signo) + int signo; +{ + + syslog(LOG_ERR, "got signal %d", signo); + dologout(1); +} + #ifdef VIRTUAL_HOSTING /* * read in virtual host tables (if they exist) @@ -1727,7 +1753,7 @@ pdata_err: * * NB: Form isn't handled. */ -static void +static int send_data(instr, outstr, blksize, filesize, isreg) FILE *instr, *outstr; off_t blksize; @@ -1740,14 +1766,12 @@ send_data(instr, outstr, blksize, filesize, isreg) off_t cnt; transflag++; - if (setjmp(urgcatch)) { - transflag = 0; - return; - } switch (type) { case TYPE_A: while ((c = getc(instr)) != EOF) { + if (recvurg) + goto got_oob; byte_count++; if (c == '\n') { if (ferror(outstr)) @@ -1756,6 +1780,8 @@ send_data(instr, outstr, blksize, filesize, isreg) } (void) putc(c, outstr); } + if (recvurg) + goto got_oob; fflush(outstr); transflag = 0; if (ferror(instr)) @@ -1763,7 +1789,7 @@ send_data(instr, outstr, blksize, filesize, isreg) if (ferror(outstr)) goto data_err; reply(226, "Transfer complete."); - return; + return (0); case TYPE_I: case TYPE_L: @@ -1785,6 +1811,8 @@ send_data(instr, outstr, blksize, filesize, isreg) while (err != -1 && cnt < filesize) { err = sendfile(filefd, netfd, offset, len, (struct sf_hdtr *) NULL, &cnt, 0); + if (recvurg) + goto got_oob; byte_count += cnt; offset += cnt; len -= cnt; @@ -1798,14 +1826,14 @@ send_data(instr, outstr, blksize, filesize, isreg) } reply(226, "Transfer complete."); - return; + return (0); } oldway: if ((buf = malloc((u_int)blksize)) == NULL) { transflag = 0; perror_reply(451, "Local resource failure: malloc"); - return; + return (-1); } while ((cnt = read(filefd, buf, (u_int)blksize)) > 0 && @@ -1819,21 +1847,28 @@ oldway: goto data_err; } reply(226, "Transfer complete."); - return; + return (0); default: transflag = 0; reply(550, "Unimplemented TYPE %d in send_data", type); - return; + return (-1); } data_err: transflag = 0; perror_reply(426, "Data connection"); - return; + return (-1); file_err: transflag = 0; perror_reply(551, "Error on input file"); + return (-1); + +got_oob: + myoob(); + recvurg = 0; + transflag = 0; + return (-1); } /* @@ -1851,11 +1886,6 @@ receive_data(instr, outstr) char buf[BUFSIZ]; transflag++; - if (setjmp(urgcatch)) { - transflag = 0; - return (-1); - } - bare_lfs = 0; switch (type) { @@ -1863,10 +1893,14 @@ receive_data(instr, outstr) case TYPE_I: case TYPE_L: while ((cnt = read(fileno(instr), buf, sizeof(buf))) > 0) { + if (recvurg) + goto got_oob; if (write(fileno(outstr), buf, cnt) != cnt) goto file_err; byte_count += cnt; } + if (recvurg) + goto got_oob; if (cnt < 0) goto data_err; transflag = 0; @@ -1879,6 +1913,8 @@ receive_data(instr, outstr) case TYPE_A: while ((c = getc(instr)) != EOF) { + if (recvurg) + goto got_oob; byte_count++; if (c == '\n') bare_lfs++; @@ -1894,6 +1930,8 @@ receive_data(instr, outstr) (void) putc(c, outstr); contin2: ; } + if (recvurg) + goto got_oob; fflush(outstr); if (ferror(instr)) goto data_err; @@ -1922,6 +1960,12 @@ file_err: transflag = 0; perror_reply(452, "Error writing file"); return (-1); + +got_oob: + myoob(); + recvurg = 0; + transflag = 0; + return (-1); } void @@ -2341,9 +2385,16 @@ dologout(status) } static void -myoob(signo) +sigurg(signo) int signo; { + + recvurg = 1; +} + +static void +myoob() +{ char *cp; /* only process if transfer occurring */ @@ -2359,7 +2410,6 @@ myoob(signo) tmpline[0] = '\0'; reply(426, "Transfer aborted. Data connection closed."); reply(226, "Abort successful"); - longjmp(urgcatch, 1); } if (strcmp(cp, "STAT\r\n") == 0) { tmpline[0] = '\0'; @@ -2675,10 +2725,6 @@ send_file_list(whichf) simple = 1; } - if (setjmp(urgcatch)) { - transflag = 0; - goto out; - } while ((dirname = *dirlist++)) { if (stat(dirname, &st) < 0) { /* @@ -2720,6 +2766,13 @@ send_file_list(whichf) while ((dir = readdir(dirp)) != NULL) { char nbuf[MAXPATHLEN]; + if (recvurg) { + myoob(); + recvurg = 0; + transflag = 0; + goto out; + } + if (dir->d_name[0] == '.' && dir->d_namlen == 1) continue; if (dir->d_name[0] == '.' && dir->d_name[1] == '.' && |
